如何允许Laravel和WordPress共享登录名? [英] How to allow Laravel and WordPress to share logins?

查看:53
本文介绍了如何允许Laravel和WordPress共享登录名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Laravel开发人员.我使用Laravel开发了一个电子商务插件,我只想将WordPress与Laravel结合使用.因此,我需要在Laravel和WordPress之间共享或进行常见的登录会话.

I'm a Laravel developer. I develop one ecommerce plugin with Laravel and I just want to combine WordPress with Laravel. So I need to share or make common login session between Laravel and WordPress.

我该如何实施?并为此提供特殊的插件吗?还是可以使用laravel-Auth?

How could I implement this? And are there special plugins available for this? Or could I use laravel-Auth?

推荐答案

在WordPress中启用单一登录使我花了18个小时以上的时间,但可能只花了几分钟:

我尝试了各种方法: Laravel护照(OAuth2), OpenID Connect ,等等.

Enabling Single-Sign-On in WordPress took me 18+ hours of struggle but might take you only a few minutes:

I experimented with all sorts of things: Laravel Passport (OAuth2), OpenID Connect, etc.

但是我唯一可以使用的解决方案是让WordPress登录页面重定向到受auth保护的Laravel路由,该路由会生成JWT(JSON Web令牌),然后重定向回WordPress上的特殊回调URL,这会创建一个新用户或登录现有用户.

But the only solution I could get to work was to have the WordPress login page redirect to an auth-protected Laravel route that generates a JWT (JSON Web Token) and redirects back to a special callback URL on WordPress that either creates a new user or logs in an existing user.

效果很好.

class JwtController extends Controller {

    /**
     * Inspired by https://github.com/WebDevStudios/aad-first-party-sso-wordpress/tree/master/lib/php-jwt
     * 
     * @param Request $request
     * @return ResponseInterface
     */
    public function redirectWithToken(Request $request) {
        $key = config('jwt.key');
        $wpJwtUrl = $request->input('callback');
        $redirectUrlAfterLogin = $request->input('redirect_to'); //Get the original intended destination and append as URL param to /jwt. 
        $tokenArray = $this->getToken(auth()->user(), $redirectUrlAfterLogin);
        $jwt = \Firebase\JWT\JWT::encode($tokenArray, $key);
        $wpJwtUrlWithTokenAsParam = $wpJwtUrl . '?token=' . $jwt;
        return redirect()->away($wpJwtUrlWithTokenAsParam);
    }

    /**
     * 
     * @param \App\User $user
     * @param string $redirectUrlAfterLogin
     * @return array
     */
    public function getToken($user, $redirectUrlAfterLogin) {
        $now = \Carbon\Carbon::now();
        $aud = config('jwt.audience'); //root URL of the WordPress site
        $firstName = StrT::getFirstNameFromFullName($user->name);
        $expirationMins = config('jwt.expirationMins');
        $token = [
            "iss" => url("/"),
            "aud" => $aud, //"audience" https://tools.ietf.org/html/rfc7519#section-4.1.3
            "iat" => $now->timestamp, //"issued at" https://tools.ietf.org/html/rfc7519#section-4.1.6
            "exp" => $now->addMinutes($expirationMins)->timestamp, //"expiration" https://tools.ietf.org/html/rfc7519#section-4.1.4
            "attributes" => [
                'emailAddress' => $user->email,
                'firstName' => $firstName,
                'lastName' => StrT::getLastNameFromFullName($user->name),
                'nickname' => $firstName,
                'displayName' => $user->name,
                'redirectUrlAfterLogin' => $redirectUrlAfterLogin//In plugin: use redirectUrlAfterLogin from attributes after login.
            ]
        ];
        return $token;
    }
}

  • 安装此WordPress插件,但在完成所有其他操作之前,不要激活它: https://as.wordpress.org/plugins/jwt -authenticator/
    • Install this WordPress plugin, but don't activate it until you're finished with everything else: https://wordpress.org/plugins/wp-force-login/
    • Install this WordPress plugin: https://as.wordpress.org/plugins/jwt-authenticator/
    • 然后将其auth.php编辑为:

      And then edit its auth.php to be this:

      // register the callback
      add_action('rest_api_init', function () {
          register_rest_route('jwt-auth/v1', 'callback', [
              'methods' => 'GET',
              'callback' => 'ja_login'
                  ], true);
      });
      
      require_once('JWT.php');
      
      function ja_login() {
          //get all attributes
          $options = get_option('ja_settings');
          $token_name = $options['token_name'];
          $secret_key = $options['secret_key'];
          $iss = $options['iss'];
          $aud = $options['aud'];
      
          // decode the token
          $token = $_GET[$token_name];
          $key = $secret_key;
          $JWT = new JWT;
          $json = $JWT->decode($token, $key);
          $jwt = json_decode($json, true);
      
          // use unix time for comparision
          $exp = is_int($jwt['exp']) ? $jwt['exp'] : strtotime($jwt['exp']);
          $nbf = $jwt['nbf'] ?? null;
          $now = strtotime("now");
      
          // if authentication successful
          if (($jwt['iss'] == $iss) && ($jwt['aud'] == $aud) && ($exp > $now) && ($now > $nbf)) {
              return getUserFromValidToken($options, $jwt);
          } else {
              return 'Login failed. Please let us know exactly what happened, and we will help you out right away.';
          }
      }
      
      /**
       * 
       * @param array $options
       * @param array $jwt
       * @return string
       */
      function getUserFromValidToken($options, $jwt) {
          $attributesKey = $options['attributes'];
          $mail = $options['mail'];
          $givenname = $options['first_name'];
          $surname = $options['last_name'];
          $nickname = $options['nickname'];
          $displayname = $options['displayname'];
          $default_role = $options['default_role'];    
          $attributes = $jwt[$attributesKey];
          $redirectUrlAfterLogin = $attributes['redirectUrlAfterLogin'] ?? get_site_url();
          $_SESSION['attributes'] = $attributes;
          $_SESSION['jwt'] = $jwt;
      
          // find or create user
          $user = ja_find_or_create_user($attributes[$mail], $attributes[$mail], $attributes[$givenname], $attributes[$surname], $attributes[$nickname], $attributes[$displayname], $default_role);
          // login user
          if ($user) {
              wp_clear_auth_cookie();
              wp_set_current_user($user->ID, $user->user_login);
              wp_set_auth_cookie($user->ID);
              do_action('wp_login', $user->user_login);        
              wp_safe_redirect($redirectUrlAfterLogin);
              exit();
          } else {
              return 'getUserFromValidToken failed!';
          }
      }
      
      /**
       * 
       * @param string $username
       * @param string $emailAddress
       * @param string $firstName
       * @param string $lastName
       * @param string $nickname
       * @param string $displayName
       * @param string $defaultRole
       * @return mixed 
       */
      function ja_find_or_create_user($username, $emailAddress, $firstName, $lastName, $nickname, $displayName, $defaultRole) {
          // if user exists, return user
          if (username_exists($username)) {
              return get_user_by('login', $username);
          } elseif (email_exists($emailAddress)) {
              return get_user_by('email', $emailAddress);
          } else {//  create user
              $length = 16;
              $include_standard_special_chars = false;
              $random_password = wp_generate_password($length, $include_standard_special_chars);
              // create user
              $user_id = wp_create_user($username, $random_password, $emailAddress);
              // update user metadata and return user id
              $userData = [
                  'ID' => $user_id,
                  'first_name' => $firstName,
                  'last_name' => $lastName,
                  'nickname' => $nickname,
                  'display_name' => $displayName,
                  'role' => $defaultRole
              ];
              return wp_update_user($userData);//(If successful, returns the user_id, otherwise returns a WP_Error object.)
          }
      }
      
      /**
       * Get login message link HTML for adding to the login form
       * @return string
       */
      function getLoginMessage() {
          $options = get_option('ja_settings');
          $redirect_to = $_GET['redirect_to'] ?? null;
          $login_url = $options['login_url'] . '?callback=' . urlencode(site_url('/wp-json/jwt-auth/v1/callback'));
          if($redirect_to){
              $login_url .= '&redirect_to=' . urlencode($redirect_to);
          }
          $login_message = $options['login_message'];
          return "<a id='jwt_link' href='{$login_url}'>{$login_message}</a>";
      }
      
      add_filter('login_message', 'getLoginMessage');
      add_action( 'load-profile.php', function() {//https://wordpress.stackexchange.com/a/195370/51462 Redirect from profile.php to the dashboard since there is no reason for WordPress users to see or manage their profile since their main account is on the other site.
          if( ! current_user_can( 'manage_options' ) ){
              $redirectUrl = get_site_url();//admin_url()
              exit( wp_safe_redirect( $redirectUrl ) );
          }
      } );
      function show_admin_bar_conditionally(){//remove the WordPress admin toolbar https://premium.wpmudev.org/blog/remove-the-wordpress-admin-toolbar/
          return current_user_can( 'manage_options' );
      }
      add_filter('show_admin_bar', 'show_admin_bar_conditionally');//can use 'show_admin_bar_conditionally' or '__return_false' for never.
      //------------------------------------------------------------------
      //for https://wordpress.org/support/topic/rest-api-26/#post-9915078 
      //and https://github.com/kevinvess/wp-force-login/issues/35 
      //and https://wordpress.org/support/topic/rest-api-26/page/2/#post-10000740
      //and https://wordpress.org/support/topic/jwt-authentication/#post-10698307
      add_filter( 'rest_authentication_errors', '__return_true' );
      

      这属于WordPress中主题的functions.php:

      This belongs in functions.php of your theme in WordPress:

      // https://codex.wordpress.org/Customizing_the_Login_Form
      function my_custom_login_page() { ?>
          <style type="text/css">
              #loginform, #login #nav{display: none;}
              #jwt_link{font-weight: bold; font-size: 20px;}
          </style>
          <script>
              document.addEventListener("DOMContentLoaded", function(event) { 
                  document.getElementById('jwt_link').click();//immediately upon load of login page, click the JWT link automatically
              });
          </script>
      <?php }
      add_action( 'login_enqueue_scripts', 'my_custom_login_page' );
      

      这篇关于如何允许Laravel和WordPress共享登录名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆