oauth2.0及oauth2-server 库在thinkphp6中的使用

目录

1.OAuth2.0

2.四种模式

3.oauth2运行流程

4.jwt

5.安装

6.授权码模式

6.1代码实例

6.2相关Repository和Entity执行流程(接口实现见 官方文档)

6.3.刷新令牌

6.4验证令牌(中间件)

 7.隐式授权

 8.密码模式

9.客户端模式 


1.OAuth2.0

OAuth2.0 定义了四个角色

Client:客户端,第三方应用程序。
Resource Owner:资源所有者,授权 Client 访问其帐户的用户。
Authorization server:授权服务器,服务商专用于处理用户授权认证的服务器。
Resource server:资源服务器,服务商用于存放用户受保护资源的服务器,它可以与授权服务器是同一台服务器,也可以是不同的服务器。

oauth2-server

Access token:用于访问受保护资源的令牌。
Authorization code:发放给应用程序的中间令牌,客户端应用使用此令牌交换 access token。
Scope:授予应用程序的权限范围。
JWT:Json Web Token 是一种用于安全传输的数据传输格式。(重点部分)

2.四种模式

1)授权码模式(authorization code)
这种模式是最安全的OAuth2的授权模式。设计了auth code,通过这个code再获取token,最后通过token获取资源。支持refresh token

2)简单模式(implicit)
和授权码模式类似,只不过少了获取code的步骤,是直接获取令牌token的,适用于公开的浏览器单页应用,令牌直接从授权服务器返回,不支持刷新令牌,且没有code安全保证,令牌容易因为被拦截窃听而泄露。不支持refresh token

3)密码模式(resource owner password credentials)
这种模式是最不推荐的,因为client可能存了用户密码
这种模式主要用来做遗留项目升级为oauth2的适配方案
当然如果client是自家的应用,也是可以。支持refresh token

4)客户端模式(client credentials)
这种模式直接根据client的id和密钥即可获取token,无需用户参与
这种模式比较合适消费api的后端服务,比如拉取一组用户信息等
不支持refresh token,主要是没有必要

个别参数说明

scope:权限范围,可选项,以空格分隔
state:CSRF令牌,可选项,但强烈建议使用,应将该值存储于用户会话中,以便在返回时验证

scope的理解 关于OAuth2 Scope的理解 – 编织梦想的猫  

3.oauth2运行流程

4.jwt

jwt使用一种特殊格式的token,token是有特定含义的,分为三部分:

头部Header
在header中通常包含了两部分:token类型和采用的加密算法。如下:

{
"alg": "HS256",   #加密方式
"typ": "JWT"        #token的类型为jwt
}

载荷Payload,可以添加自定义参数

{
    "aud": "myapp",                            #接收该JWT的一方
    "jti": "9cf3dde8d0dd28fe5c678acb3161354128d627b12638c78c40f32bafe3e6fc",
    "iat": 1629360641.99316,            #在什么时候签发的
    "nbf": 1629360641.993166,
    "exp": 1629364241.990516,        #什么时候过期,这里是一个Unix时间戳
    "sub": "300000",                         #该JWT所面向的用户
    "scopes": ["basic"]                        #权限范围
}

签名Signature

将Header和Payload通过'.'拼接起来,再根据header中的加密方式加密,然后再base64即可得到signature
最后这三部分均用base64进行编码,并使用.进行分隔。一个典型的jwt格式的token类似xxxx.yyy.zzz。

$accessToken = $request->header('authorization');
$arr = explode('.', $accessToken);
$uid = json_decode(base64_decode($arr[1]))->sub;

JSON Web Tokens (JWT) 在线解密

5.安装

composer require league/oauth2-server

注意

1. 8.x版本需要php7.4版本,否则会报 AccessToken::__toString() must not throw an exception 也可以使用7.2 安装lcobucci/jwt 3.4.6 详见官网安装配置要求

2. 7.x的版本需要将jwt库降级为3.3.3,否则会报 Replicating claims as headers is deprecated and will removed from v4.0. Please manually set the header if you need it replicated

composer require lcobucci/jwt 3.3.3

 官方文档:OAuth 2.0 Server - PHP, meet OAuth 2 (有很多框架的例子就是没有thinkPHP的)

6.授权码模式

6.1代码实例

生成私钥公钥

openssl genrsa -out private.key 2048 生成私钥(无密码)
openssl rsa -in private.key -pubout -out public.key 私钥换取公钥(无密码)
openssl genrsa -aes128 -passout pass:_passphrase_ -out private.key 2048 生成私钥(有密码)
openssl rsa -in private.key -passin pass:_passphrase_ -pubout -out public.key 私钥换取公钥(有密码)

 初始化服务

public function codeGrantInit(){
    $clientRepository = new ClientRepository();
    $scopeRepository = new ScopeRepository();
    $accessTokenRepository = new AccessTokenRepository();
    $authCodeRepository = new AuthCodeRepository();
    $refreshTokenRepository = new RefreshTokenRepository();

    $privateKeyPath = root_path() . 'private.key';

    $server = new AuthorizationServer(
        $clientRepository,
        $accessTokenRepository,
        $scopeRepository,
        $privateKeyPath, '');

    //设置模式
    try {
        $grant = new AuthCodeGrant(
            $authCodeRepository,
            $refreshTokenRepository,
            new DateInterval('PT10M') // authorization codes will expire after 10 minutes
        );

        //设置RefreshToken的生命周期
        $grant->setRefreshTokenTTL(new DateInterval('P1M'));

        $server->enableGrantType(
            $grant,
            new DateInterval('PT1H') // access tokens will expire after 1 hour
        );

        return $server;
    } catch (\Exception $e) {
        throw new BaseException($e->getMessage());
    }
}

第一步:用户访问客户端,客户端将用户导向授权服务器。【获取code,用户可见】【用户在客户端】
请求方式:get
请求参数 :response_type=code、client_id、redirect_uri、scope、state

public function authorize(){
    $oauth = new Oauth2Service();
    $server = $oauth->codeGrantInit();
    $request = ServerRequest::fromGlobals();
    $response = new Response();
    try {
        #1.验证HTTP请求并返回AuthorizationRequest对象
        //这里是三方应用请求给授权服务器的。授权服务器验证
        //生成code时,只是验证了client_id必须,以及redirect_uri不为空时,是否与client_id对应的redirect_uri匹配,
        $authRequest = $server->validateAuthorizationRequest($request);
        // 此时应将 authRequest 对象序列化后存在当前会话(session)中
        session('authRequest', serialize($authRequest));
        #2.用户没有登录,增跳转到授权服务的登录【qq】  是pc端;11
        // 然后将用户重定向至登录入口或在当前地址直接响应登录页面
        return View::fetch('index/auth_code');
    } catch (OAuthServerException $exception) {
        throw new BaseException($exception->getMessage());
    } catch (\Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

第二步:要求用户登录授权服务器并批准客户端  【用户在授权服务器端
这里登录和授权实际是两步这里只做了一步。数据库中存储的是code的唯一标识,code标识加上其他参数转json后再通过encrypt加密既是返回值

public function agree(){
    $oauth = new Oauth2Service();
    $server = $oauth->codeGrantInit();
    $response = new Response();
    try {
        // 在会话(session)中取出 authRequest 对象
        $authRequest = unserialize(session('authRequest'));
        //1、登录验证成功,设置用户实体(userEntity)【jwt中的sub】
        $user = new UserEntity();
        $authRequest->setUser($user->login());

        //2、设置权限范围【jwt中的scope】
        $scope = new ScopeEntity();
        $scope->setIdentifier('basic');
        $scopes[] = $scope;
        $authRequest->setScopes($scopes);

        #批准客户端
        $authRequest->setAuthorizationApproved(true);
        //完成后重定向至客户端请求重定向地址
        $response = $server->completeAuthorizationRequest($authRequest, $response);
        $redirectUrl = $response->getHeaders()['Location'][0];

        #将auth_code返回给重定向地址
        return redirect($redirectUrl);
    } catch (OAuthServerException $exception) {
        throw new BaseException($exception->getMessage());
    } catch (Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

返回值auth_code的组成

$payload = [
    'client_id'             => $authCode->getClient()->getIdentifier(),
    'redirect_uri'          => $authCode->getRedirectUri(),
    'auth_code_id'          => $authCode->getIdentifier(),
    'scopes'                => $authCode->getScopes(),
    'user_id'               => $authCode->getUserIdentifier(),
    'expire_time'           => (new DateTimeImmutable())->add($this->authCodeTTL)->getTimestamp(),
    'code_challenge'        => $authorizationRequest->getCodeChallenge(),//null
    'code_challenge_method' => $authorizationRequest->getCodeChallengeMethod(),//null
];
$jsonPayload = \json_encode($payload);
//无关代码省略
$this->encrypt($jsonPayload);

第三步:获取access_token。【用户不可见,由客户后端执行】
请求方式:post
需要的参数:grant_type=authorization_code、client_id、client_secret、redirect_uri、code

public function accessToken(){
    $oauth = new Oauth2Service();
    $server = $oauth->codeGrantInit();
    $request = ServerRequest::fromGlobals();
    $response = new Response();
    try {
        // 这里只需要这一行就可以,具体的判断在 Repositories 中
        $response = $server->respondToAccessTokenRequest($request, $response);
        return response(json_decode($response->getBody()), 200, [], 'json');
    } catch (OAuthServerException $exception) {
        throw new BaseException($exception->getMessage());
    } catch (Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

 access_token返回值方法

1.(string) $this->accessToken; //BearerTokenResponse类中,此时$this->AccessTokenEntity
2.触发AccessTokenTrait的__toString();即return $this->convertToJWT()->toString();
3.生成jwt格式的acess_token

 返回实例:access_token是jwt格式

{"token_type":"Bearer","expires_in":3600,"access_token":"xxxxxx","refresh_token":"xxxx"}

 access_token解密后的结果:

{ "typ": "JWT","alg": "RS256"}   #HEADER
{"aud": "test", "jti": "2cb...", "iat": 1629771757.03695,"nbf": 1629771757.036958,"exp": 1629775357.028548,"sub": "300000","scopes": ["oauth2"]} #PAYLOAD

 rerfresh_token的组成

$refreshTokenPayload = \json_encode([
    'client_id'        => $this->accessToken->getClient()->getIdentifier(),
    'refresh_token_id' => $this->refreshToken->getIdentifier(),
    'access_token_id'  => $this->accessToken->getIdentifier(),
    'scopes'           => $this->accessToken->getScopes(),
    'user_id'          => $this->accessToken->getUserIdentifier(),
    'expire_time'      => $this->refreshToken->getExpiryDateTime()->getTimestamp(),
]);
$responseParams['refresh_token'] = $this->encrypt($refreshTokenPayload);

6.2相关Repository和Entity执行流程(接口实现见 官方文档

 oauth2-server 的新版本并没有指定某种数据库,所以它可以使用任何形式的数据存储方式。代价就是必须开发者自己实现...

/authorize路由中:validateAuthorizationRequest()

ClientRepository->getClientEntity ()                         
#通过查询数据库,验证client_id,并返回cient对象
ScopeRepository->getScopeEntityByIdentifier()        
#通过查询数据库,验证授权服务器是否支持该权限

 /agree路由中:completeAuthorizationRequest()

AuthCodeRepository->getNewAuthCode()                         
#创建新授权码时调用方法,需要返回 AuthCodeEntityInterface 对象
AuthCodeRepository->persistNewAuthCode()        
#用于持久化存储授权码,持久化数据库自行选择

 /access_token路由中:respondToAccessTokenRequest()

ClientRepository->getClientEntity()                         
#通过查询数据库,验证client_id,并返回cient对象
ClientRepository->validateClient()      
#验证客户端,包括(client_secret,redirect_uri,is_confidential,name)
ClientRepository->getClientEntity() 
#验证code前,也需要验证client_id;
AuthCodeRepository->isAuthCodeRevoked()
#当【使用授权码获取访问令牌时】调用此方法,用于验证授权码是否已被使用
ScopeRepository->getScopeEntityByIdentifier()        
#通过查询数据库,验证授权服务器是否支持该权限
ScopeRepository->finalizeScopes()
#用于验证权限范围、授权类型、客户端、用户是否匹配 ,必须返回 ScopeEntityInterface对象 
AccessTokenRepository->getNewToken()   
#返回AccessTokenEntityInterface对象,在返回前向 AccessTokenEntity 传入参数中对应属性.
AccessTokenRepository->persistNewAccessToken()
#可以用于持久化存储访问令牌,持久化数据库自行选择
RefreshTokenRepository->getNewRefreshToken()
#要返回 RefreshTokenEntityInterface 对象
RefreshTokenRepository->persistNewRefreshToken()
#用于持久化存储授刷新令牌
AuthCodeRepository->revokeAuthCode()
#可以在此时将授权码从持久化数据库中删除

6.3.刷新令牌

创建服务

public function refreshTokenGrantInit(){
    $clientRepository = new ClientRepository();
    $scopeRepository = new ScopeRepository();
    $accessTokenRepository = new AccessTokenRepository();
    $refreshTokenRepository = new RefreshTokenRepository();

    $privateKeyPath = root_path() . 'private.key';

    $server = new AuthorizationServer(
        $clientRepository,
        $accessTokenRepository,
        $scopeRepository,
        $privateKeyPath, '');
    //设置模式
    try {
        $grant = new RefreshTokenGrant($refreshTokenRepository);
        //设置RefreshToken的生命周期
        $grant->setRefreshTokenTTL(new DateInterval('P1M'));
        $server->enableGrantType(
            $grant,
            new DateInterval('PT1H') // access tokens will expire after 1 hour
        );
        return $server;
    } catch (\Exception $e) {
        throw new BaseException($e->getMessage());
    }
}

相关Repository执行流程
 /refresh_token路由中:respondToAccessTokenRequest() 

ClientRepository -> validateClient()      
#验证客户端,包括(client_secret,redirect_uri,is_confidential,name)
ClientRepository -> getClientEntity() 
#验证code前,也需要验证client_id;
RefreshTokenRepository -> isRefreshTokenRevoked()
#当【刷新令牌获取访问令牌时】调用此方法,用于验证刷新令牌是否已被删除
ScopeRepository -> getScopeEntityByIdentifier()        
#通过查询数据库,验证授权服务器是否支持该权限
AccessTokenRepository -> revokeAccessToken()
#使用刷新令牌创建新的访问令牌时调用此方法,可将token在持久化存储中过期
ScopeRepository -> revokeRefreshToken()
#使用刷新令牌获取访问令牌时调用此方法,原刷新令牌将删除,创建新的刷新令牌
AccessTokenRepository -> getNewToken()   
#返回AccessTokenEntityInterface对象,在返回前向 AccessTokenEntity 传入参数中对应属性.
AccessTokenRepository -> persistNewAccessToken()
#可以用于持久化存储访问令牌,持久化数据库自行选择
RefreshTokenRepository -> getNewRefreshToken()
#要返回 RefreshTokenEntityInterface 对象
RefreshTokenRepository -> persistNewRefreshToken()
#用于持久化存储授刷新令牌
AuthCodeRepository -> revokeAuthCode()
#可以在此时将授权码从持久化数据库中删除

6.4验证令牌(中间件)

class AccessTokenMiddleware{
    public function handle($request, \Closure $next)
    {
        $publicKeyPath = root_path() . 'public.key'; // 授权服务器分发的公钥
        $accessTokenRepository = new AccessTokenRepository();
        $bearerTokenValidator = new BearerTokenValidator($accessTokenRepository);
        $bearerTokenValidator->setPublicKey(new CryptKey($publicKeyPath, null, false));
        try {
            $bearerTokenValidator->validateAuthorization(ServerRequest::fromGlobals());
            return $next($request); 
        }catch (OAuthServerException $exception) {
            throw new BaseException($exception->getHint());
        }catch (\Exception $exception) {
            throw new BaseException($exception->getMessage());
        }
    }
}

 相关Repository

AccessTokenRepository -> isAccessTokenRevoked()
#用于验证访问令牌是否已被删除,正常情况下,一个token会多次使用,这里可以使用缓存 

 7.隐式授权

整个流程与授权码模式的第一部分类似,只是授权服务器直接响应了访问令牌,跳过了授权码的步骤。它适用于没有服务器,完全运行在前端的应用程序

此模式下没有刷新令牌(refresh token)的返回。

创建服务

public function implicitGrantInit(){
    $clientRepository = new ClientRepository();
    $scopeRepository = new ScopeRepository();
    $accessTokenRepository = new AccessTokenRepository();
    $privateKeyPath = root_path() . 'private.key';
    
    $server = new AuthorizationServer(
        $clientRepository,
        $accessTokenRepository,
        $scopeRepository,
        $privateKeyPath, '');  //encryptionKey,用于auth_code 的加密
    //设置模式
    try {
        $server->enableGrantType(
            new ImplicitGrant(new \DateInterval('PT1H')),
            new \DateInterval('PT1H') // 设置访问令牌过期时间1小时
        );
        return $server;
    } catch (\Exception $e) {
        throw new BaseException($e->getMessage());
    }
}

请求实例:实际可能是两步(1、用户访问客户端,客户端将用户导向授权服务器。2、用户登录并授权),这里用一步完成。
请求方式:post
参数:response_type=token、client_id、redirect_uri、scope、state
注意:这里授权服务器会重定向到redirect_uri,在redirect_uri后会带上 #access_token=xxx

public function authorize(){
    $oauth = new Oauth2Service();
    $request = ServerRequest::fromGlobals();
    $response = new Response();
    try {
        $server = $oauth->implicitGrantInit();
        $authRequest = $server->validateAuthorizationRequest($request);
        //1、登录验证成功,设置用户实体(userEntity)【jwt中的sub】
        $user = new UserEntity();
        $authRequest->setUser($user->login());

        //2、设置权限范围【假如多个可选,列表展示客户端的权限】【jwt中的scope】
        $scope = new ScopeEntity();
        $scope->setIdentifier('oauth2');
        $scopes[] = $scope;
        $authRequest->setScopes($scopes);

        #批准客户端
        $authRequest->setAuthorizationApproved(true);
        //完成后重定向至客户端请求重定向地址
        $response = $server->completeAuthorizationRequest($authRequest, $response);
        $redirectUrl = $response->getHeaders()['Location'][0];
        return redirect($redirectUrl);
    }catch (OAuthServerException $exception) {
        throw new BaseException($exception->getHint());
    }  catch (Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

返回值:token_type、expires_in、access_token、state
返回实例:redirect_uri#access_token=eyJ0...&token_type=Bearer&expires_in=3600&state=1

 8.密码模式

由用户提供给客户端账号密码来获取访问令牌,这属于危险行为,所以此模式只适用于高度信任的客户端(例如第一方应用程序)。客户端不应存储用户的账号密码

OAuth2 协议规定此模式不需要传 client_id & client_secret,但 oauth-server 库需要

创建服务

public function pwdGrantInit(){
    $clientRepository = new ClientRepository();
    $scopeRepository = new ScopeRepository();
    $accessTokenRepository = new AccessTokenRepository();
    $privateKeyPath = root_path() . 'private.key';

    $server = new AuthorizationServer(
        $clientRepository,
        $accessTokenRepository,
        $scopeRepository,
        $privateKeyPath, '');  //encryptionKey,用于auth_code 的加密

    $userRepository = new UserRepository();
    $refreshTokenRepository = new RefreshTokenRepository();
    try {
        $grant = new PasswordGrant(
            $userRepository,
            $refreshTokenRepository
        );

        $grant->setRefreshTokenTTL(new \DateInterval('P1M')); // refresh tokens will expire after 1 month

        $server->enableGrantType(
            $grant,
            new \DateInterval('PT1H') // access tokens will expire after 1 hour
        );
        return $server;
    } catch (\Exception $e) {
        throw new BaseException($e->getMessage());
    }
}

请求方式:post
参数:grant_type=password、client_id、client_secret、scope、username、password

public function accessToken(){
    //先验证必传参数
    $oauth = new Oauth2Service();
    $request = ServerRequest::fromGlobals();
    $response = new Response();
    try {
        $server = $oauth->pwdGrantInit();
        // 这里只需要这一行就可以,具体的判断在 Repositories 中
        $response = $server->respondToAccessTokenRequest($request, $response);
        return response(json_decode($response->getBody()), 200, [], 'json');
    } catch (OAuthServerException $exception) {
        throw new BaseException($exception->getHint());
    } catch (Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

返回值:token_type、expires_in、access_token、refresh_token

相关Repository执行流程

ClientRepository->validateClient()      
#验证客户端,包括(client_secret,redirect_uri,is_confidential,name)
ClientRepository->getClientEntity()                         
#通过查询数据库,验证client_id,并返回cient对象
ScopeRepository->getScopeEntityByIdentifier()        
#通过查询数据库,验证授权服务器是否支持该权限
ScopeRepository->finalizeScopes()
#用于验证权限范围、授权类型、客户端用户是否匹配 ,必须返回 ScopeEntityInterface对象 
AccessTokenRepository->getNewToken()   
#返回AccessTokenEntityInterface对象,在返回前向 AccessTokenEntity 传入参数中对应属性.
AccessTokenRepository->persistNewAccessToken()
#可以用于持久化存储访问令牌,持久化数据库自行选择
RefreshTokenRepository->getNewRefreshToken()
#要返回 RefreshTokenEntityInterface 对象
RefreshTokenRepository->persistNewRefreshToken()
#用于持久化存储授刷新令牌

9.客户端模式 

客户端模式是指以客户端的名义,而不是用户的名义,向授权服务器获取认证。在这个模式下,用户与授权服务器不产生关系,用户只能感知到的客户端所产生的资源【公共资源和单个用户无关】也都由客户端处理。

创建服务

public function clientGrantInit(){
    $clientRepository = new ClientRepository();
    $scopeRepository = new ScopeRepository();
    $accessTokenRepository = new AccessTokenRepository();
    $privateKeyPath = root_path() . 'private.key';

    $server = new AuthorizationServer(
        $clientRepository,
        $accessTokenRepository,
        $scopeRepository,
        $privateKeyPath, '');  //encryptionKey,用于auth_code 的加密

    try {
        $server->enableGrantType(
            new ImplicitGrant(new \DateInterval('PT1H')),
            new \DateInterval('PT1H') // 设置访问令牌过期时间1小时
        );
        return $server;
    } catch (\Exception $e) {
        throw new BaseException($e->getMessage());
    }
}

请求方式:post
参数:grant_type=client_credentials、client_id、client_secret、scope

public function accessToken(){
    //先验证必传参数
    $oauth = new Oauth2Service();
    $request = ServerRequest::fromGlobals();
    $response = new Response();
    try {
        $server = $oauth->clientGrantInit(); //只是服务不同
        // 这里只需要这一行就可以,具体的判断在 Repositories 中
        $response = $server->respondToAccessTokenRequest($request, $response);
        return response(json_decode($response->getBody()), 200, [], 'json');
    } catch (OAuthServerException $exception) {
        throw new BaseException($exception->getHint());
    } catch (Exception $exception) {
        throw new BaseException($exception->getMessage());
    }
}

返回值:token_type、expires_in、access_token

相关Repository执行流程

ClientRepository->getClientEntity()                         
#通过查询数据库,验证client_id,并返回cient对象
ClientRepository->validateClient()      
#验证客户端,包括(client_secret,redirect_uri,is_confidential,name)
ClientRepository->getClientEntity() 
#验证code前,也需要验证client_id;
ScopeRepository->getScopeEntityByIdentifier()        
#通过查询数据库,验证授权服务器是否支持该权限
ScopeRepository->finalizeScopes()
#用于验证权限范围、授权类型、客户端、用户是否匹配 ,必须返回 ScopeEntityInterface对象 
AccessTokenRepository->getNewToken()   
#返回AccessTokenEntityInterface对象,在返回前向 AccessTokenEntity 传入参数中对应属性.
AccessTokenRepository->persistNewAccessToken()
#可以用于持久化存储访问令牌,持久化数据库自行选择

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
ThinkPHP6 使用 `league/oauth2-server` 可以按照以下步骤进行: 1. 安装 `league/oauth2-server`: ```bash composer require league/oauth2-server ``` 2. 创建 `AuthorizationServer` 和 `ResourceServer` 实例: ```php use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\ResourceServer; $authorizationServer = new AuthorizationServer(); $resourceServer = new ResourceServer(); ``` 3. 配置 `AuthorizationServer`: ```php use League\OAuth2\Server\Grant\ClientCredentialsGrant; use League\OAuth2\Server\Repositories\ClientRepository; $clientRepository = new ClientRepository(); $authorizationServer->enableGrantType( new ClientCredentialsGrant(), new \DateInterval('PT1H') // access token 有效时间为 1 小时 ); $authorizationServer->setClientRepository($clientRepository); ``` 4. 创建 `AccessTokenController`,处理 access token 请求: ```php use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use League\OAuth2\Server\RequestTypes\AccessTokenRequest; use League\OAuth2\Server\ResponseTypes\JsonResponse; class AccessTokenController { public function index() { $authorizationServer = new AuthorizationServer(); $accessTokenRequest = AccessTokenRequest::createFromGlobals(); $response = new JsonResponse(); try { $accessTokenResponse = $authorizationServer->respondToAccessTokenRequest( $accessTokenRequest, $response ); return $accessTokenResponse; } catch (\Exception $e) { return $response->setError( $e->getMessage(), $e->getCode() ); } } } ``` 5. 创建 `ResourceController`,处理需要 access token 的资源请求: ```php use League\OAuth2\Server\RequestTypes\ResourceRequest; class ResourceController { public function index() { $resourceServer = new ResourceServer(); $resourceRequest = ResourceRequest::createFromGlobals(); try { $resourceServer->validateAuthenticatedRequest($resourceRequest); // 处理资源请求 } catch (\Exception $e) { // 处理验证失败 } } } ``` 6. 配置路由: ```php use think\facade\Route; Route::post('access_token', 'AccessTokenController@index'); Route::get('resource', 'ResourceController@index')->middleware(\think\middleware\JwtAuth::class); ``` 以上是一个简单的使用 `league/oauth2-server` 的示例,在实际项目需要根据具体需求进行更详细的配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值