Browse Source
- `UserInfoIdentitySession` 标记为已过时 - 增加 `ValidationTokenCheckIdentitySession` 用于验证过程中检查会话 - 增加 `ServerValidationTokenCheckIdentitySession` 用于授权过程中检查会话pull/1416/head
7 changed files with 105 additions and 69 deletions
@ -0,0 +1,43 @@ |
|||||
|
using LINGYUN.Abp.Identity.Session; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using OpenIddict.Server; |
||||
|
using System.Security.Principal; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using static OpenIddict.Abstractions.OpenIddictConstants; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.AspNetCore.Session; |
||||
|
public class ServerValidationTokenCheckIdentitySession : IOpenIddictServerHandler<OpenIddictServerEvents.ValidateTokenContext> |
||||
|
{ |
||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||
|
protected IIdentitySessionChecker IdentitySessionChecker { get; } |
||||
|
|
||||
|
public static OpenIddictServerHandlerDescriptor Descriptor { get; } = |
||||
|
OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.ValidateTokenContext>() |
||||
|
.UseSingletonHandler<ServerValidationTokenCheckIdentitySession>() |
||||
|
.SetOrder(OpenIddictServerHandlers.Protection.ValidatePrincipal.Descriptor.Order + 2_000) |
||||
|
.SetType(OpenIddictServerHandlerType.Custom).Build(); |
||||
|
|
||||
|
public ServerValidationTokenCheckIdentitySession( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IIdentitySessionChecker identitySessionChecker) |
||||
|
{ |
||||
|
CurrentTenant = currentTenant; |
||||
|
IdentitySessionChecker = identitySessionChecker; |
||||
|
} |
||||
|
|
||||
|
public async virtual ValueTask HandleAsync(OpenIddictServerEvents.ValidateTokenContext context) |
||||
|
{ |
||||
|
var tenantId = context.Principal.FindTenantId(); |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
if (!await IdentitySessionChecker.ValidateSessionAsync(context.Principal)) |
||||
|
{ |
||||
|
context.Logger.LogWarning("The token is no longer valid because the user's session expired."); |
||||
|
// Errors.InvalidToken ---> 401
|
||||
|
// Errors.ExpiredToken ---> 400
|
||||
|
context.Reject(Errors.InvalidToken, "The user session has expired."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using LINGYUN.Abp.Identity.Session; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using OpenIddict.Validation; |
||||
|
using System.Security.Principal; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using static OpenIddict.Abstractions.OpenIddictConstants; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.AspNetCore.Session; |
||||
|
public class ValidationTokenCheckIdentitySession : IOpenIddictValidationHandler<OpenIddictValidationEvents.ValidateTokenContext> |
||||
|
{ |
||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||
|
protected IIdentitySessionChecker IdentitySessionChecker { get; } |
||||
|
|
||||
|
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } |
||||
|
= OpenIddictValidationHandlerDescriptor.CreateBuilder<OpenIddictValidationEvents.ValidateTokenContext>() |
||||
|
.UseSingletonHandler<ValidationTokenCheckIdentitySession>() |
||||
|
.SetOrder(OpenIddictValidationHandlers.Protection.ValidatePrincipal.Descriptor.Order + 2_000) |
||||
|
.SetType(OpenIddictValidationHandlerType.Custom) |
||||
|
.Build(); |
||||
|
|
||||
|
public ValidationTokenCheckIdentitySession( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IIdentitySessionChecker identitySessionChecker) |
||||
|
{ |
||||
|
CurrentTenant = currentTenant; |
||||
|
IdentitySessionChecker = identitySessionChecker; |
||||
|
} |
||||
|
|
||||
|
public async virtual ValueTask HandleAsync(OpenIddictValidationEvents.ValidateTokenContext context) |
||||
|
{ |
||||
|
var tenantId = context.Principal.FindTenantId(); |
||||
|
using (CurrentTenant.Change(tenantId)) |
||||
|
{ |
||||
|
if (!await IdentitySessionChecker.ValidateSessionAsync(context.Principal)) |
||||
|
{ |
||||
|
context.Logger.LogWarning("The token is no longer valid because the user's session expired."); |
||||
|
// Errors.InvalidToken ---> 401
|
||||
|
// Errors.ExpiredToken ---> 400
|
||||
|
context.Reject(Errors.InvalidToken, "The user session has expired."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,62 +0,0 @@ |
|||||
using OpenIddict.Abstractions; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Security.Claims; |
|
||||
using Volo.Abp.Users; |
|
||||
using VoloUserInfoController = Volo.Abp.OpenIddict.Controllers.UserInfoController; |
|
||||
|
|
||||
namespace LINGYUN.Abp.OpenIddict.AspNetCore.Controllers; |
|
||||
|
|
||||
[ExposeServices( |
|
||||
typeof(VoloUserInfoController), |
|
||||
typeof(UserInfoController))] |
|
||||
public class UserInfoController : VoloUserInfoController |
|
||||
{ |
|
||||
protected async override Task<Dictionary<string, object>> GetUserInfoClaims() |
|
||||
{ |
|
||||
var user = await UserManager.GetUserAsync(User); |
|
||||
if (user == null) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
var claims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
||||
{ |
|
||||
// Note: the "sub" claim is a mandatory claim and must be included in the JSON response.
|
|
||||
[OpenIddictConstants.Claims.Subject] = await UserManager.GetUserIdAsync(user), |
|
||||
[AbpClaimTypes.SessionId] = CurrentUser.FindSessionId(), |
|
||||
}; |
|
||||
|
|
||||
if (User.HasScope(OpenIddictConstants.Scopes.Profile)) |
|
||||
{ |
|
||||
claims[AbpClaimTypes.TenantId] = user.TenantId; |
|
||||
claims[OpenIddictConstants.Claims.PreferredUsername] = user.UserName; |
|
||||
claims[OpenIddictConstants.Claims.FamilyName] = user.Surname; |
|
||||
claims[OpenIddictConstants.Claims.GivenName] = user.Name; |
|
||||
} |
|
||||
|
|
||||
if (User.HasScope(OpenIddictConstants.Scopes.Email)) |
|
||||
{ |
|
||||
claims[OpenIddictConstants.Claims.Email] = await UserManager.GetEmailAsync(user); |
|
||||
claims[OpenIddictConstants.Claims.EmailVerified] = await UserManager.IsEmailConfirmedAsync(user); |
|
||||
} |
|
||||
|
|
||||
if (User.HasScope(OpenIddictConstants.Scopes.Phone)) |
|
||||
{ |
|
||||
claims[OpenIddictConstants.Claims.PhoneNumber] = await UserManager.GetPhoneNumberAsync(user); |
|
||||
claims[OpenIddictConstants.Claims.PhoneNumberVerified] = await UserManager.IsPhoneNumberConfirmedAsync(user); |
|
||||
} |
|
||||
|
|
||||
if (User.HasScope(OpenIddictConstants.Scopes.Roles)) |
|
||||
{ |
|
||||
claims[OpenIddictConstants.Claims.Role] = await UserManager.GetRolesAsync(user); |
|
||||
} |
|
||||
|
|
||||
// Note: the complete list of standard claims supported by the OpenID Connect specification
|
|
||||
// can be found here: http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
|
|
||||
|
|
||||
return claims; |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue