OAuth2.0是目前主流的授权协议,广泛用于第三方登录、接口权限管控等场景,在PHP架构中集成OAuth2.0需要结合项目现有分层结构,同时理清不同授权模式的流程逻辑,才能保障集成后的稳定性和安全性。

OAuth2.0核心角色说明
在集成之前需要先明确OAuth2.0的四个核心角色,避免后续流程理解出现偏差:
- 资源所有者:通常是终端用户,拥有被访问的资源权限
- 客户端:发起授权请求的PHP应用,比如你的网站或者接口调用方
- 授权服务器:负责验证用户身份、发放访问令牌的服务端
- 资源服务器:存储受保护资源,验证令牌合法性后返回对应数据的服务端
PHP架构中集成OAuth2.0的步骤
1. 依赖引入与基础配置
如果是Laravel等主流PHP框架,可以直接使用对应的OAuth2.0扩展包,比如league/oauth2-server,如果是原生PHP项目也可以手动引入该包。首先通过Composer安装依赖:
composer require league/oauth2-server
安装完成后需要配置授权服务器的基础参数,包括私钥、公钥、令牌有效期等:
<?php
// 配置OAuth2.0授权服务器
use LeagueOAuth2ServerAuthorizationServer;
use LeagueOAuth2ServerGrantAuthCodeGrant;
use LeagueOAuth2ServerRepositoriesClientRepositoryInterface;
use LeagueOAuth2ServerRepositoriesScopeRepositoryInterface;
use LeagueOAuth2ServerRepositoriesAuthCodeRepositoryInterface;
use LeagueOAuth2ServerRepositoriesRefreshTokenRepositoryInterface;
// 实例化所需仓库类(需自己实现对应接口)
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$authCodeRepository = new AuthCodeRepository();
$refreshTokenRepository = new RefreshTokenRepository();
// 创建授权服务器实例
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
'file:///path/to/private.key', // 私钥路径
'file:///path/to/public.key', // 公钥路径
new LeagueOAuth2ServerEncryptionKey('your-encryption-key')
);
// 启用授权码模式
$server->enableGrantType(
new AuthCodeGrant(
$authCodeRepository,
$refreshTokenRepository,
new DateInterval('PT10M') // 授权码有效期10分钟
),
new DateInterval('PT1H') // 访问令牌有效期1小时
);
2. 路由与控制器适配
需要在PHP项目的路由层添加对应的授权相关路由,比如授权页面路由、令牌获取路由、资源访问路由,同时在控制器中处理对应的逻辑:
<?php
// 授权页面路由处理
public function authorize(Request $request)
{
try {
// 验证授权请求
$authRequest = $this->server->validateAuthorizationRequest($request);
// 这里可以展示用户授权页面,让用户确认是否授权
// 用户确认后执行下面的授权逻辑
return $this->server->completeAuthorizationRequest($authRequest, $request);
} catch (LeagueOAuth2ServerExceptionOAuthServerException $exception) {
return $exception->generateHttpResponse(new GuzzleHttpPsr7Response());
}
}
// 令牌获取路由处理
public function token(Request $request)
{
try {
return $this->server->respondToAccessTokenRequest($request, new GuzzleHttpPsr7Response());
} catch (LeagueOAuth2ServerExceptionOAuthServerException $exception) {
return $exception->generateHttpResponse(new GuzzleHttpPsr7Response());
}
}
3. 资源服务器的令牌验证
资源服务器需要验证客户端携带的访问令牌是否合法,在PHP项目中可以添加中间件实现统一验证:
<?php
// 令牌验证中间件
public function handle(Request $request, Closure $next)
{
$resourceServer = new LeagueOAuth2ServerResourceServer(
$this->accessTokenRepository,
'file:///path/to/public.key' // 公钥路径
);
try {
$request = $resourceServer->validateAuthenticatedRequest($request);
return $next($request);
} catch (LeagueOAuth2ServerExceptionOAuthServerException $exception) {
return response()->json(['error' => 'invalid_token'], 401);
}
}
常见授权流程详解
授权码模式流程(最常用)
授权码模式是安全性最高的模式,适合有后端的PHP应用,流程如下:
- 客户端引导用户跳转到授权服务器的授权页面,携带客户端ID、重定向地址、请求的权限范围等参数
- 用户在授权页面确认授权,授权服务器生成授权码,重定向回客户端指定的地址,将授权码作为查询参数传递
- 客户端收到授权码后,携带客户端密钥、授权码、重定向地址等参数向授权服务器请求访问令牌
- 授权服务器验证参数合法后,返回访问令牌和刷新令牌
- 客户端携带访问令牌向资源服务器请求受保护资源,资源服务器验证令牌合法后返回数据
密码模式流程
密码模式适合第一方应用,用户需要直接提供账号密码,流程如下:
- 客户端收集用户的账号和密码,直接携带客户端ID、客户端密钥、账号密码等参数向授权服务器请求令牌
- 授权服务器验证账号密码和客户端信息合法后,返回访问令牌和刷新令牌
- 客户端使用访问令牌访问资源服务器的受保护资源
集成注意事项
- 私钥和公钥需要妥善保管,不要提交到公开代码仓库
- 授权码、访问令牌的有效期需要根据业务场景合理设置,避免过长带来安全风险
- 重定向地址需要严格校验,防止授权码被劫持
- 令牌传输需要使用HTTPS协议,避免令牌在传输过程中被窃取
如果是在本地开发环境测试,授权服务器和资源服务器可以部署在同一个PHP项目中,生产环境建议分开部署,降低单点风险。