diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/CurrentUser/HttpContextCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/CurrentUser/HttpContextCurrentPrincipalAccessor.cs new file mode 100644 index 00000000..efdbac8e --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/CurrentUser/HttpContextCurrentPrincipalAccessor.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.CurrentUsers.Accessor; + +namespace Yi.Framework.AspNetCore.CurrentUser +{ + public class HttpContextCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpContextCurrentPrincipalAccessor(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return _httpContextAccessor.HttpContext?.User ?? base.GetClaimsPrincipal(); + } + + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CurrentUserUseExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CurrentUserUseExtensions.cs deleted file mode 100644 index f97c9fc0..00000000 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/AspNetCore/Builder/CurrentUserUseExtensions.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; -using Yi.Framework.Core.Const; -using Yi.Framework.Core.CurrentUsers; - -namespace Microsoft.AspNetCore.Builder -{ - public static class CurrentUserUseExtensions - { - public static IApplicationBuilder UseCurrentUserServer(this IApplicationBuilder app) - { - return app.UseMiddleware(); - } - - - } - - public class CurrentUserMiddleware - { - - private readonly RequestDelegate _next; - private ILogger _logger; - public CurrentUserMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } - - public async Task Invoke(HttpContext context, ICurrentUser _currentUser) - { - var authenticateContext = await context.AuthenticateAsync(); - if (authenticateContext.Principal is null) - { - _currentUser.IsAuthenticated = false; - await _next(context); - return; - } - var claims = authenticateContext.Principal.Claims; - //通过鉴权之后,开始赋值 - _currentUser.IsAuthenticated = true; - _currentUser.Id = claims.GetClaim(TokenTypeConst.Id) is null ? 0 : Convert.ToInt64(claims.GetClaim(TokenTypeConst.Id)); - _currentUser.UserName = claims.GetClaim(TokenTypeConst.UserName) ?? ""; - _currentUser.Permission = claims.GetClaims(TokenTypeConst.Permission); - _currentUser.TenantId = claims.GetClaim(TokenTypeConst.TenantId) is null ? null : Guid.Parse(claims.GetClaim(TokenTypeConst.TenantId)!); - await _next(context); - - } - - - - } - - public static class ClaimExtension - { - public static string? GetClaim(this IEnumerable claims, string type) - { - return claims.Where(c => c.Type == type).Select(c => c.Value).FirstOrDefault(); - } - - public static string[]? GetClaims(this IEnumerable claims, string type) - { - return claims.Where(c => c.Type == type).Select(c => c.Value).ToArray(); - } - } -} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs index 801b8a48..130d6090 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/CurrentUserAddExtensions.cs @@ -9,8 +9,10 @@ using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; +using Yi.Framework.AspNetCore.CurrentUser; using Yi.Framework.Core.Const; using Yi.Framework.Core.CurrentUsers; +using Yi.Framework.Core.CurrentUsers.Accessor; namespace Microsoft.Extensions.DependencyInjection { @@ -18,7 +20,8 @@ namespace Microsoft.Extensions.DependencyInjection { public static IServiceCollection AddCurrentUserServer(this IServiceCollection services) { - return services.AddScoped(); + services.AddSingleton(); + return services.AddTransient(); } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs index 4274dd1c..08043a7f 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/YiFrameworkAspNetCoreModule.cs @@ -7,6 +7,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Yi.Framework.AspNetCore.CurrentUser; +using Yi.Framework.Core.CurrentUsers.Accessor; +using Yi.Framework.Core.CurrentUsers; namespace Yi.Framework.AspNetCore { @@ -15,12 +18,13 @@ namespace Yi.Framework.AspNetCore public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) { - app.UseCurrentUserServer(); } public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) { + services.AddHttpContextAccessor(); services.AddCurrentUserServer(); + } } } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs new file mode 100644 index 00000000..06dd9632 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/CurrentPrincipalAccessorBase.cs @@ -0,0 +1,32 @@ +using System.Security.Claims; +using Yi.Framework.Core.Utils; + +namespace Yi.Framework.Core.CurrentUsers.Accessor +{ + public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor + { + public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); + + private readonly AsyncLocal _currentPrincipal = new AsyncLocal(); + + protected abstract ClaimsPrincipal GetClaimsPrincipal(); + + public virtual IDisposable Change(ClaimsPrincipal principal) + { + return SetCurrent(principal); + } + + private IDisposable SetCurrent(ClaimsPrincipal principal) + { + var parent = Principal; + _currentPrincipal.Value = principal; + return new DisposeAction, ClaimsPrincipal>>(static (state) => + { + var (currentPrincipal, parent) = state; + currentPrincipal.Value = parent; + }, (_currentPrincipal, parent)); + + } + } + +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs new file mode 100644 index 00000000..50dff9c4 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ICurrentPrincipalAccessor.cs @@ -0,0 +1,11 @@ +using System.Security.Claims; + +namespace Yi.Framework.Core.CurrentUsers.Accessor +{ + public interface ICurrentPrincipalAccessor + { + ClaimsPrincipal Principal { get; } + IDisposable Change(ClaimsPrincipal principal); + } + +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs new file mode 100644 index 00000000..83c24746 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/StaticCurrentPrincipalAccessor.cs @@ -0,0 +1,15 @@ +using System.Security.Claims; + +using Yi.Framework.Core.CurrentUsers.Accessor; + +namespace SF.CurrentUser.CS.Accessor +{ + public class StaticPrincipalAccessor : CurrentPrincipalAccessorBase + { + public static ClaimsPrincipal ClaimsPrincipal { get; set; } + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return ClaimsPrincipal; + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs new file mode 100644 index 00000000..f4138299 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/Accessor/ThreadCurrentPrincipalAccessor.cs @@ -0,0 +1,13 @@ +using System.Security.Claims; + +namespace Yi.Framework.Core.CurrentUsers.Accessor +{ + public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase + { + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return Thread.CurrentPrincipal as ClaimsPrincipal; + } + } + +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs index 9ca4688c..ea961dd5 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs @@ -1,31 +1,79 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Text; using System.Threading.Tasks; +using Yi.Framework.Core.Const; +using Yi.Framework.Core.CurrentUsers.Accessor; namespace Yi.Framework.Core.CurrentUsers { public class CurrentUser : ICurrentUser { - public bool IsAuthenticated { get; set; } + private readonly ICurrentPrincipalAccessor _principalAccessor; + public CurrentUser(ICurrentPrincipalAccessor principalAccessor) + { + _principalAccessor = principalAccessor; + } + public bool IsAuthenticated => Id != 0; - public long Id { get; set; } + public long Id => FindUserId(); - public string UserName { get; set; } = string.Empty; + public string UserName => this.FindClaimValue(TokenTypeConst.UserName); - public Guid? TenantId { get; set; } + /// + /// 暂时为默认值 + /// + public Guid TenantId { get; set; } = Guid.Empty; - public string Email { get; set; } = string.Empty; + public string Email => FindClaimValue(TokenTypeConst.Email); - public bool EmailVerified { get; set; } + public bool EmailVerified=> false; - public string PhoneNumber { get; set; } = string.Empty; + public string PhoneNumber => FindClaimValue(TokenTypeConst.PhoneNumber); - public bool PhoneNumberVerified { get; set; } + public bool PhoneNumberVerified => false; - public string[]? Roles { get; set; } + public string[]? Roles => this.FindClaims(TokenTypeConst.Roles).Select(c => c.Value).Distinct().ToArray(); - public string[]? Permission { get; set; } + public string[]? Permission => this.FindClaims(TokenTypeConst.Permission).Select(c => c.Value).Distinct().ToArray(); + + public virtual Claim FindClaim(string claimType) + { + return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType); + } + + public virtual Claim[] FindClaims(string claimType) + { + return _principalAccessor.Principal?.Claims.Where(c => c.Type == claimType).ToArray() ?? new Claim[0]; + } + + public virtual Claim[] GetAllClaims() + { + return _principalAccessor.Principal?.Claims.ToArray() ?? new Claim[0]; + } + + public string FindClaimValue(string claimType) + { + return FindClaim(claimType)?.Value; + } + + + public long FindUserId() + { + var userIdOrNull = _principalAccessor.Principal.Claims?.FirstOrDefault(c => c.Type == TokenTypeConst.Id); + if (userIdOrNull == null || string.IsNullOrWhiteSpace(userIdOrNull.Value)) + { + return 0; + } + + if (long.TryParse(userIdOrNull.Value, out long userId)) + { + return userId; + } + + return 0; + } } -} +} \ No newline at end of file diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs index d70a0d1f..8364db9c 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs @@ -8,24 +8,24 @@ namespace Yi.Framework.Core.CurrentUsers { public interface ICurrentUser { - public bool IsAuthenticated { get; set; } - public long Id { get; set; } + public bool IsAuthenticated { get; } + public long Id { get; } - public string UserName { get; set; } + public string UserName { get; } - public Guid? TenantId { get; set; } + public Guid TenantId { get; } - public string Email { get; set; } + public string Email { get; } - public bool EmailVerified { get; set; } + public bool EmailVerified { get; } - public string PhoneNumber { get; set; } + public string PhoneNumber { get; } - public bool PhoneNumberVerified { get; set; } + public bool PhoneNumberVerified { get; } - public string[]? Roles { get; set; } + public string[]? Roles { get; } - public string[]? Permission { get; set; } + public string[]? Permission { get; } } } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs new file mode 100644 index 00000000..e1cff0ac --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Utils/DisposeAction.cs @@ -0,0 +1,27 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Yi.Framework.Core.Utils +{ + public class DisposeAction : IDisposable + { + private readonly Action _action; + + private readonly T _parameter; + + /// + /// Creates a new object. + /// + /// Action to be executed when this object is disposed. + /// The parameter of the action. + public DisposeAction(Action action, T parameter) + { + _action = action; + _parameter = parameter; + } + + public void Dispose() + { + _action(_parameter); + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Ddd/Repositories/IRepository.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Ddd/Repositories/IRepository.cs index b9605f86..2a999aa7 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Ddd/Repositories/IRepository.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Ddd/Repositories/IRepository.cs @@ -33,7 +33,6 @@ namespace Yi.Framework.Ddd.Repositories Task> GetPageListAsync(Expression> whereExpression, IPagedAndSortedResultRequestDto page, Expression>? orderByExpression = null, OrderByEnum orderByType = OrderByEnum.Asc); Task> GetPageListAsync(Expression> whereExpression, IPagedAndSortedResultRequestDto page, string? orderBy, OrderByEnum orderByType = OrderByEnum.Asc); - //插入 Task InsertAsync(T insertObj); Task InsertOrUpdateAsync(T data);