要在laravel中实现单点登录(sso),核心思路是建立一个中心化的认证服务并通过oauth 2.0或openid connect协议实现跨应用统一认证,具体步骤如下:1. 建立中心认证服务器(laravel应用a):安装laravel passport并执行迁移与安装命令;配置user模型使用hasapitokens trait;设置api守卫驱动为passport;在authserviceprovider中调用passport::routes()注册路由;创建oauth客户端用于子应用接入。2. 配置客户端应用(laravel应用b、c等):用户未登录时重定向至认证中心构造授权url;回调处理获取code并请求access_token;使用token获取用户信息后本地登录用户;保持登录状态通过存储token实现;登出时需撤销认证中心token并销毁本地会话。此外,实施过程中需注意安全性问题,如令牌存储应采用httponly cookie或后端session管理,并设置短生命周期token配合刷新机制;同时要确保全局登出、正确配置cors、校验redirect_uri及state参数防止csrf攻击;推荐优先采用oauth 2.0/ openid connect方案以获得更高的安全性和扩展性。

要在Laravel中实现单点登录(SSO),核心思路是建立一个中心化的认证服务,让用户只需在一个地方登录,就能无缝访问多个独立的Laravel应用。这通常通过OAuth 2.0或OpenID Connect协议来完成,其中一个Laravel应用充当认证服务器,其他应用则作为客户端。
实现Laravel中的单点登录,我通常会倾向于使用Laravel Passport,因为它为OAuth 2.0的实现提供了非常便利的工具。
1. 建立中心认证服务器(Laravel应用A)
首先,你需要一个主应用来处理所有用户的认证逻辑,我们就叫它“认证中心”吧。
安装Laravel Passport: 在你的认证中心应用中,安装Passport:
composer require laravel/passport php artisan migrate php artisan passport:install
passport:install 命令会创建加密密钥和一些默认的客户端,这些是后续认证流程的基础。
配置用户模型:
确保你的User模型使用了HasApiTokens trait:
// app/Models/User.php
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
// ...
}配置认证守卫:
在config/auth.php中,将api守卫的驱动设置为passport:
// config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
],
'api' => [
'driver' => 'passport', // 这里
'provider' => 'users',
],
],定义认证路由:
Passport提供了标准的OAuth 2.0授权码流程。你需要在AuthServiceProvider中调用Passport::routes()来注册这些路由:
// app/Providers/AuthServiceProvider.php
use Laravel\Passport\Passport;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Passport::routes(); // 注册Passport路由
// ...
}
}创建OAuth客户端:
对于每一个需要接入SSO的子应用,你都需要在认证中心创建一个OAuth客户端。你可以手动在数据库中创建,或者使用php artisan passport:client --password或php artisan passport:client --personal来创建。对于授权码流程,你需要一个“授权码”类型的客户端。
2. 配置客户端应用(Laravel应用B, C...)
现在,每个需要通过SSO登录的Laravel应用都将是认证中心的“客户端”。
重定向到认证中心: 当用户尝试访问客户端应用但未登录时,客户端应用需要将用户重定向到认证中心的登录页面。这通常发生在自定义的认证中间件或控制器中。 例如,你可以构造一个OAuth授权URL:
// 在客户端应用中
public function redirectToAuthServer()
{
$query = http_build_query([
'client_id' => 'your-client-id', // 在认证中心创建的客户端ID
'redirect_uri' => 'http://client-app.test/auth/callback', // 客户端回调URL
'response_type' => 'code',
'scope' => '', // 请求的权限范围
]);
return redirect('http://auth-server.test/oauth/authorize?' . $query);
}处理回调并获取访问令牌:
用户在认证中心登录并授权后,认证中心会将用户重定向回客户端应用的回调URL(redirect_uri),并附带一个code参数。客户端应用需要用这个code去认证中心交换access_token。
// 在客户端应用的回调路由中 (e.g., /auth/callback)
use GuzzleHttp\Client;
public function handleAuthCallback(Request $request)
{
$http = new Client();
try {
$response = $http->post('http://auth-server.test/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'your-client-id',
'client_secret' => 'your-client-secret', // 客户端密钥
'redirect_uri' => 'http://client-app.test/auth/callback',
'code' => $request->code,
],
]);
$tokenData = json_decode((string) $response->getBody(), true);
// 将 access_token 和 refresh_token 存储起来(例如,在session或数据库中)
session(['access_token' => $tokenData['access_token']]);
session(['refresh_token' => $tokenData['refresh_token']]);
// 使用 access_token 获取用户信息
$userResponse = $http->get('http://auth-server.test/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $tokenData['access_token'],
],
]);
$userData = json_decode((string) $userResponse->getBody(), true);
// 在客户端应用中创建或更新用户,并使其登录
// 例如:Auth::login(User::firstOrCreate([...]));
return redirect('/dashboard'); // 重定向到应用内部页面
} catch (\Exception $e) {
// 处理错误,比如授权失败
return redirect('/login')->with('error', '认证失败:' . $e->getMessage());
}
}保持登录状态:
一旦客户端应用获取到access_token和用户信息,它就可以在本地创建一个会话,让用户保持登录状态。后续对认证中心受保护资源的访问,都带着access_token即可。
登出逻辑:
当用户在任何一个客户端应用登出时,除了销毁本地会话外,最好也向认证中心发送请求,撤销对应的access_token,确保全局登出。
// 登出时
public function logout(Request $request)
{
// 撤销认证中心的 token
$http = new Client();
try {
$http->post('http://auth-server.test/oauth/tokens/revoke', [
'headers' => [
'Authorization' => 'Bearer ' . session('access_token'),
],
]);
} catch (\Exception $e) {
// 即使撤销失败,也继续本地登出
Log::error("Failed to revoke token: " . $e->getMessage());
}
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}单点登录无疑极大地提升了用户体验,用户只需记住一套凭证,就能穿梭于多个系统之间,减少了重复登录的烦恼和密码疲劳。但同时,它也引入了新的安全考量,平衡这两者是SSO设计的核心挑战。
从用户体验角度看,SSO的优势显而易见:登录流程简化,尤其是在企业内部或产品生态系统中,用户感知到的流畅度会大大提升。我个人非常喜欢这种“无感”的切换,它让整个系统显得更加统一和专业。
然而,安全性方面,SSO就像把所有鸡蛋放在一个篮子里。认证中心一旦被攻破,所有依赖它的应用都会面临风险。这要求认证中心本身具备极高的安全防护能力,包括但不限于:
我发现,许多人在实施SSO时,往往只关注了“能用”,而忽略了“安全地用”。比如,把access_token直接存在localStorage里,或者没有一个健全的令牌刷新和撤销机制,这都是非常危险的。正确的做法是,对于Web应用,access_token最好通过HttpOnly的Cookie来传递,或者通过后端Session管理,而refresh_token则需要更严格的保护。
在Laravel生态中实现SSO,确实有几种不同的思路,每种都有其适用场景和优缺点。我经常会根据项目的具体需求、应用间的耦合程度以及未来的扩展性来做选择。
本系统经过多次升级改造,系统内核经过多次优化组合,已经具备相对比较方便快捷的个性化定制的特性,用户部署完毕以后,按照自己的运营要求,可实现快速定制会费管理,支持在线缴费和退费功能财富中心,管理会员的诚信度数据单客户多用户登录管理全部信息支持审批和排名不同的会员级别有不同的信息发布权限企业站单独生成,企业自主决定更新企业站信息留言、询价、报价统一管理,分系统查看分类信息参数化管理,支持多样分类信息,
0
OAuth 2.0 / OpenID Connect (OIDC):
JWT (JSON Web Tokens):
access_token。access_token载体,可以提供无状态的API访问。共享会话/Cookie:
app1.example.com和app2.example.com)。domain属性为顶级域名,Laravel的Session机制就能自动跨子域名共享。总的来说,对于大多数现代Laravel应用,我强烈建议优先考虑OAuth 2.0 / OpenID Connect,配合Laravel Passport,它能提供最健壮、最灵活且符合行业标准的SSO解决方案。JWT则可以作为OAuth令牌的一种形式,用于API认证。
单点登录听起来很美,但在实际落地过程中,总会遇到一些预料之外的坑。我自己在处理SSO项目时,也踩过不少雷,这里总结一些常见的陷阱和我的应对策略。
陷阱1:令牌存储不当导致安全隐患
access_token存储在浏览器localStorage中。这看起来很方便,但localStorage容易受到XSS攻击,一旦页面被注入恶意脚本,令牌就可能被窃取。access_token或一个代表用户会话的标识符存储在HttpOnly的Cookie中。HttpOnly的Cookie无法通过JavaScript访问,大大降低了XSS攻击的风险。access_token后,可以在后端服务器创建一个会话,并将access_token存储在服务器端的Session中。客户端浏览器只维护一个Session ID的Cookie。access_token被窃取,由于其生命周期短,攻击者可利用的时间也有限。同时,refresh_token应该存储在更安全的地方,并且只能使用一次,或者有严格的IP限制。陷阱2:登出逻辑不完整,导致“假登出”
access_token和refresh_token。Laravel Passport提供了oauth/tokens/revoke接口。陷阱3:跨域资源共享(CORS)配置不当
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等CORS响应头。barryvdh/laravel-cors这样的包可以简化CORS配置,你可以根据需要设置允许的来源、方法和头部。陷阱4:性能瓶颈集中在认证中心
access_token的有效期,减少客户端频繁请求新令牌的次数,通过refresh_token来续期。陷阱5:授权回调URL(redirect_uri)未严格校验
redirect_uri是认证中心将用户重定向回客户端的地址。如果认证中心不严格校验这个URL,恶意攻击者可以构造一个恶意的redirect_uri,将授权码发送到自己的服务器,从而劫持用户会话。redirect_uri必须与预注册的白名单完全匹配。state参数,并将其存储在会话中。认证中心重定向回来时,客户端验证state参数是否匹配,以防止CSRF攻击。这些都是我在实践中总结出的一些经验,希望对你有所帮助。SSO的实现并非一蹴而就,它需要对安全、性能和用户体验进行全面的考量和持续的优化。
以上就是如何在Laravel中实现单点登录的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号