【.NET Core项目实战-统一认证平台】第十一章 授权篇-密码授权模式 (3)

根据不同的授权模式,生成不同的token记录。

/// <summary> /// Processes the response. /// </summary> /// <param>The request.</param> /// <returns></returns> public virtual async Task<TokenResponse> ProcessAsync(TokenRequestValidationResult request) { switch (request.ValidatedRequest.GrantType) { case OidcConstants.GrantTypes.ClientCredentials: return await ProcessClientCredentialsRequestAsync(request); case OidcConstants.GrantTypes.Password: //生成密码授权模式token return await ProcessPasswordRequestAsync(request); case OidcConstants.GrantTypes.AuthorizationCode: return await ProcessAuthorizationCodeRequestAsync(request); case OidcConstants.GrantTypes.RefreshToken: return await ProcessRefreshTokenRequestAsync(request); default: return await ProcessExtensionGrantRequestAsync(request); } } /// <summary> /// Creates the response for a password request. /// </summary> /// <param>The request.</param> /// <returns></returns> protected virtual Task<TokenResponse> ProcessPasswordRequestAsync(TokenRequestValidationResult request) { Logger.LogTrace("Creating response for password request"); return ProcessTokenRequestAsync(request); } /// <summary> /// Creates the response for a token request. /// </summary> /// <param>The validation result.</param> /// <returns></returns> protected virtual async Task<TokenResponse> ProcessTokenRequestAsync(TokenRequestValidationResult validationResult) { (var accessToken, var refreshToken) = await CreateAccessTokenAsync(validationResult.ValidatedRequest); var response = new TokenResponse { AccessToken = accessToken, AccessTokenLifetime = validationResult.ValidatedRequest.AccessTokenLifetime, Custom = validationResult.CustomResponse }; if (refreshToken.IsPresent()) { response.RefreshToken = refreshToken; } return response; }

根据请求的scope判断是否生成refreshToken,如果标记了offline_access,则生成refreshToken,否则不生成。

/// <summary> /// Creates the access/refresh token. /// </summary> /// <param>The request.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException">Client does not exist anymore.</exception> protected virtual async Task<(string accessToken, string refreshToken)> CreateAccessTokenAsync(ValidatedTokenRequest request) { TokenCreationRequest tokenRequest; bool createRefreshToken; //授权码模式 if (request.AuthorizationCode != null) {//是否包含RefreshToken createRefreshToken = request.AuthorizationCode.RequestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess); // load the client that belongs to the authorization code Client client = null; if (request.AuthorizationCode.ClientId != null) { client = await Clients.FindEnabledClientByIdAsync(request.AuthorizationCode.ClientId); } if (client == null) { throw new InvalidOperationException("Client does not exist anymore."); } var resources = await Resources.FindEnabledResourcesByScopeAsync(request.AuthorizationCode.RequestedScopes); tokenRequest = new TokenCreationRequest { Subject = request.AuthorizationCode.Subject, Resources = resources, ValidatedRequest = request }; } else {//是否包含RefreshToken createRefreshToken = request.ValidatedScopes.ContainsOfflineAccessScope; tokenRequest = new TokenCreationRequest { Subject = request.Subject, Resources = request.ValidatedScopes.GrantedResources, ValidatedRequest = request }; } var at = await TokenService.CreateAccessTokenAsync(tokenRequest); var accessToken = await TokenService.CreateSecurityTokenAsync(at); if (createRefreshToken) { var refreshToken = await RefreshTokenService.CreateRefreshTokenAsync(tokenRequest.Subject, at, request.Client); return (accessToken, refreshToken); } return (accessToken, null); }

5、RefreshToken持久化

当我们使用了offline_access时,就需要生成RefreshToken并进行持久化,详细的实现代码如下。

public virtual async Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client) { _logger.LogDebug("Creating refresh token"); int lifetime; if (client.RefreshTokenExpiration == TokenExpiration.Absolute) { _logger.LogDebug("Setting an absolute lifetime: " + client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } else { _logger.LogDebug("Setting a sliding lifetime: " + client.SlidingRefreshTokenLifetime); lifetime = client.SlidingRefreshTokenLifetime; } var refreshToken = new RefreshToken { CreationTime = Clock.UtcNow.UtcDateTime, Lifetime = lifetime, AccessToken = accessToken }; //存储RefreshToken并返回值 var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken); return handle; } /// <summary> /// 存储RefreshToken并返回 /// </summary> /// <param>The refresh token.</param> /// <returns></returns> public async Task<string> StoreRefreshTokenAsync(RefreshToken refreshToken) { return await CreateItemAsync(refreshToken, refreshToken.ClientId, refreshToken.SubjectId, refreshToken.CreationTime, refreshToken.Lifetime); } /// <summary> /// 创建Item /// </summary> /// <param>The item.</param> /// <param>The client identifier.</param> /// <param>The subject identifier.</param> /// <param>The created.</param> /// <param>The lifetime.</param> /// <returns></returns> protected virtual async Task<string> CreateItemAsync(T item, string clientId, string subjectId, DateTime created, int lifetime) { var handle = await HandleGenerationService.GenerateAsync(); //生成随机值 await StoreItemAsync(handle, item, clientId, subjectId, created, created.AddSeconds(lifetime)); //存储 return handle; } /// <summary> /// 存储RefreshToken /// </summary> /// <param>The key.</param> /// <param>The item.</param> /// <param>The client identifier.</param> /// <param>The subject identifier.</param> /// <param>The created.</param> /// <param>The expiration.</param> /// <returns></returns> protected virtual async Task StoreItemAsync(string key, T item, string clientId, string subjectId, DateTime created, DateTime? expiration) { key = GetHashedKey(key); var json = Serializer.Serialize(item); var grant = new PersistedGrant { Key = key, Type = GrantType, ClientId = clientId, SubjectId = subjectId, CreationTime = created, Expiration = expiration, Data = json }; await Store.StoreAsync(grant); } //IPersistedGrantStore 我们在dapper持久化时已经实现了StoreAsync方式,是不是都关联起来了。

至此,我们整个密码授权模式全部讲解完成,相信大家跟我一样完全掌握了授权的整个流程,如果需要持久化如何进行持久化流程。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxsgs.html