如何允许Laravel和WordPress共享登录信息?

5

我是一个Laravel开发人员。我使用Laravel开发了一个电子商务插件,现在我想将WordPress与Laravel结合起来。因此,我需要在Laravel和WordPress之间共享或创建公共登录会话。

我应该如何实现这个功能?是否有特殊的插件可用于此?或者我可以使用Laravel-Auth插件吗?


据我理解,这是不可能的,因为Laravel和WordPress有它们自己不同的目录结构和编码结构。如果您在Laravel中创建API并通过WordPress插件或代码进行调用,则可能会实现。即使您这样做,也必须在两端保持不同的身份验证。 - Alankar More
但是如果我使用相同的数据库呢...?还有其他的解决方案吗? - Shankar Thiyagaraajan
这意味着您的Laravel和WordPress代码将访问同一个数据库,但我认为这不可行,需要更多的研究。 - Alankar More
我使用 Corcel 插件将 WordPress 数据库作为 Laravel 数据库使用。但是,我不知道如何在 WordPress 和 Laravel 之间启用会话共享。 - Shankar Thiyagaraajan
如果登录成功,则可以从Laravel端创建一个单独的API并尝试登录,然后设置您的Laravel会话。就像OAuth的工作方式一样。但我认为会话共享不起作用。 - Neo
如果 Laravel 在 WordPress 中可用,那么 WordPress 会话对于 Laravel 是可用的,对吧?那么我们可以访问 WordPress 会话。但我的担心是:Laravel 也在会话中管理用户令牌。那么如何将 Laravel 用户令牌添加到 WordPress 会话中呢? - Shankar Thiyagaraajan
2个回答

3
正确的做法是将 Laravel(或 Wordpress)作为认证服务器并创建一个单点登录插件。我曾经在使用 Laravel 时尝试过使用 NodeBB 论坛的登录功能。
以下是我的建议步骤:
1. 查看 Laravel OAuth Server 这个包。 2. 创建或查找任何 Wordpress 的 SSO 插件。
这样,所有用户的注册和其他操作都在 Laravel 中进行,如果他们想登录到 Wordpress,他们会在 Laravel 应用程序中登录并授权访问 Wordpress。你可以像添加“Facebook 登录”一样考虑它。了解更多 wordpress SSO
不过,要处理会话和 cookies 可能存在安全问题。希望有所帮助。

3
在WordPress中启用单点登录让我花费了18多个小时的挣扎,但你可能只需要几分钟:
我尝试了各种方法:Laravel Passport(OAuth2)、OpenID Connect等等。
但是,唯一可行的解决方案是将WordPress登录页面重定向到一个受身份验证保护的Laravel路由,该路由生成JWT(JSON Web Token),并重定向回WordPress上的特殊回调URL,该URL会创建新用户或登录现有用户。
它运作良好。
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;
    }
}

然后将其auth.php编辑为以下内容:


"最初的回答"

// 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' );

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' );


感谢您提供的示例。我正在尝试按照您的方法来实现这个确切的用例。我注意到一个问题,就是在WordPress中创建用户之后,设置授权cookie并登录用户并重定向到URL的代码不起作用,cookie从未被设置。这是我所指的代码: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(); } - Arul Dhesiaseelan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接