diff --git a/Yi.Framework.Net6/Yi.Framework.sln b/Yi.Framework.Net6/Yi.Framework.sln index a6020569..a757be53 100644 --- a/Yi.Framework.Net6/Yi.Framework.sln +++ b/Yi.Framework.Net6/Yi.Framework.sln @@ -47,9 +47,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Office.Excel", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.WeChatPay", "src\module\Yi.Framework.WeChatPay\Yi.Framework.WeChatPay.csproj", "{588D0DA9-303A-4FF0-A2D1-83037E2B269F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Data", "Yi.Framework.Data\Yi.Framework.Data.csproj", "{DEE07142-32CE-4B5F-A5A3-452064EBF4A2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Data", "src\framework\Yi.Framework.Data\Yi.Framework.Data.csproj", "{DEE07142-32CE-4B5F-A5A3-452064EBF4A2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Authentication.JwtBearer", "src\framework\Yi.Framework.Authentication.JwtBearer\Yi.Framework.Authentication.JwtBearer.csproj", "{D40C583D-58BE-422D-9A57-94DECB751EB4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Auth.JwtBearer", "src\framework\Yi.Framework.Auth.JwtBearer\Yi.Framework.Auth.JwtBearer.csproj", "{D40C583D-58BE-422D-9A57-94DECB751EB4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs new file mode 100644 index 00000000..70974444 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/JwtTokenManager.cs @@ -0,0 +1,100 @@ +using JWT; +using JWT.Algorithms; +using JWT.Builder; +using JWT.Exceptions; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Auth.JwtBearer.Authentication.Options; +using Yi.Framework.Core.Helper; + +namespace Yi.Framework.Auth.JwtBearer.Authentication +{ + public class JwtTokenManager + { + private JwtTokenOptions _jwtTokenOptions; + + public JwtTokenManager(IOptions options) + { + _jwtTokenOptions = options.Value; + } + public string CreateToken(Dictionary? claimDic) + { + var token = JwtBuilder.Create() + .WithAlgorithm(new RS256Algorithm(RSAFileHelper.GetKey(), RSAFileHelper.GetKey())) + .AddClaim(ClaimName.Issuer, _jwtTokenOptions.Issuer) + .AddClaim(ClaimName.Audience, _jwtTokenOptions.Audience) + .AddClaim(ClaimName.Subject, _jwtTokenOptions.Subject) + .AddClaim(ClaimName.IssuedAt, UnixEpoch.GetSecondsSince(new DateTimeOffset(DateTime.UtcNow))) + .ExpirationTime(DateTime.Now.AddSeconds(_jwtTokenOptions.ExpSecond)); + if (claimDic is not null) + { + foreach (var d in claimDic) + { + token.AddClaim(d.Key, d.Value); + }; + } + return token.Encode(); + } + + public IDictionary? VerifyToken(string token, TokenVerifyErrorAction tokenVerifyErrorAction) + { + IDictionary? claimDic = null; + try + { + + claimDic = JwtBuilder.Create() + .WithAlgorithm(new RS256Algorithm(RSAFileHelper.GetPublicKey())) + .WithValidationParameters(ValidationParameters.Default) + .Decode>(token); + } + catch (TokenNotYetValidException ex) + { + if (tokenVerifyErrorAction.TokenNotYetValidAction is not null) + { + tokenVerifyErrorAction.TokenNotYetValidAction(ex); + } + //Console.WriteLine("Token错误"); + } + catch (TokenExpiredException ex) + { + if (tokenVerifyErrorAction.TokenExpiredAction is not null) + { + tokenVerifyErrorAction.TokenExpiredAction(ex); + } + //Console.WriteLine("Token过期"); + } + catch (SignatureVerificationException ex) + { + if (tokenVerifyErrorAction.SignatureVerificationAction is not null) + { + tokenVerifyErrorAction.SignatureVerificationAction(ex); + } + //Console.WriteLine("Token无效"); + } + catch (Exception ex) + { + if (tokenVerifyErrorAction.ErrorAction is not null) + { + tokenVerifyErrorAction.ErrorAction(ex); + } + //Console.WriteLine("Token内部错误,json序列化"); + } + return claimDic; + + } + + public class TokenVerifyErrorAction + { + public Action? TokenNotYetValidAction { get; set; } + + public Action? TokenExpiredAction { get; set; } + public Action? SignatureVerificationAction { get; set; } + + public Action? ErrorAction { get; set; } + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs new file mode 100644 index 00000000..c2643148 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/Options/JwtTokenOptions.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Auth.JwtBearer.Authentication.Options +{ + public class JwtTokenOptions + { + /// + /// 听众 + /// + public string Audience { get; set; } = string.Empty; + + /// + /// 发行者 + /// + public string Issuer { get; set; } = string.Empty; + + /// + /// 主题 + /// + public string Subject { get; set; } = string.Empty; + + /// + /// 过期时间,单位秒 + /// + public long ExpSecond { get; set; } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/YiJwtAuthenticationHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs similarity index 54% rename from Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/YiJwtAuthenticationHandler.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs index 7a0f5135..ef236eaf 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/YiJwtAuthenticationHandler.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authentication/YiJwtAuthenticationHandler.cs @@ -3,14 +3,17 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using System.Net; using System.Security.Claims; +using System.Text.Json; +using Yi.Framework.Core.Helper; -namespace Yi.Framework.Authentication.JwtBearer +namespace Yi.Framework.Auth.JwtBearer.Authentication { public class YiJwtAuthenticationHandler : IAuthenticationHandler { - public YiJwtAuthenticationHandler() + private JwtTokenManager _jwtTokenManager; + public YiJwtAuthenticationHandler(JwtTokenManager jwtTokenManager) { - + _jwtTokenManager = jwtTokenManager; } public const string YiJwtSchemeName = "YiJwtAuth"; @@ -36,13 +39,26 @@ namespace Yi.Framework.Authentication.JwtBearer /// /// /// - private AuthenticationTicket GetAuthTicket(string name, string role) + private AuthenticationTicket GetAuthTicket(IDictionary dicClaims) { - var claimsIdentity = new ClaimsIdentity(new Claim[] + List claims = new List(); + foreach (var claim in dicClaims) { - new Claim(ClaimTypes.Name, name), - new Claim(ClaimTypes.Role, role), - }, YiJwtSchemeName); + var p = (JsonElement)claim.Value; + string? resp=null; + switch (p.ValueKind) + { + + case JsonValueKind.String: + resp = p.GetString(); + break; + case JsonValueKind.Number: + resp = p.GetInt32().ToString(); + break; + } + claims.Add(new Claim(claim.Key, resp ?? "")); + } + var claimsIdentity = new ClaimsIdentity(claims.ToArray(), YiJwtSchemeName); var principal = new ClaimsPrincipal(claimsIdentity); return new AuthenticationTicket(principal, _scheme.Name); } @@ -54,29 +70,34 @@ namespace Yi.Framework.Authentication.JwtBearer /// public Task AuthenticateAsync() { - AuthenticateResult result; + AuthenticateResult result = AuthenticateResult.Fail("未发现授权令牌"); _context.Request.Headers.TryGetValue("Authorization", out StringValues values); string valStr = values.ToString(); if (!string.IsNullOrWhiteSpace(valStr)) { - //认证模拟basic认证:cusAuth YWRtaW46YWRtaW4= - string[] authVal = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(valStr.Substring(YiJwtSchemeName.Length + 1))).Split(':'); - //var loginInfo = new Dto.LoginDto() { Username = authVal[0], Password = authVal[1] }; - //var validVale = _userService.IsValid(loginInfo); - bool validVale = true; - if (!validVale) - result = AuthenticateResult.Fail("未登陆"); + var tokenHeader = valStr.Substring(0, 6); + if (tokenHeader == "Bearer") + { + var token = valStr.Substring(7); + + var claimDic = _jwtTokenManager.VerifyToken(token, new JwtTokenManager.TokenVerifyErrorAction() + { + TokenExpiredAction = (ex) => { result = AuthenticateResult.Fail("Token过期"); }, + SignatureVerificationAction = (ex) => { result = AuthenticateResult.Fail("Token效验失效"); }, + TokenNotYetValidAction = (ex) => { result = AuthenticateResult.Fail("Token完全错误"); }, + ErrorAction = (ex) => { result = AuthenticateResult.Fail("Token内部错误"); } + }); + if (claimDic is not null) + { + //成功 + result = AuthenticateResult.Success(GetAuthTicket(claimDic)); + } + } else { - //这里应该将token进行效验,然后加入解析的claim中即可 - - var ticket = GetAuthTicket("cc", "admin"); - result = AuthenticateResult.Success(ticket); + result = AuthenticateResult.Fail("授权令牌格式错误"); } - } - else - { - result = AuthenticateResult.Fail("未登陆"); + } return Task.FromResult(result); } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs new file mode 100644 index 00000000..5696c25f --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/DefaultPermissionHandler.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.CurrentUsers; + +namespace Yi.Framework.Auth.JwtBearer.Authorization +{ + public class DefaultPermissionHandler : IPermissionHandler + { + public bool IsPass(string permission, ICurrentUser currentUser) + { + return true; + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.cs new file mode 100644 index 00000000..411248b9 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/IPermissionHandler.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.CurrentUsers; + +namespace Yi.Framework.Auth.JwtBearer.Authorization +{ + public interface IPermissionHandler + { + bool IsPass(string permission,ICurrentUser currentUser); + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs new file mode 100644 index 00000000..cb77203f --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.CurrentUsers; +using Yi.Framework.Core.Exceptions; +using Yi.Framework.Core.Model; + +namespace Yi.Framework.Auth.JwtBearer.Authorization +{ + [AttributeUsage(AttributeTargets.Method)] + public class PermissionAttribute : ActionFilterAttribute + { + private string Permission { get; set; } + + public PermissionAttribute(string permission) + { + this.Permission = permission; + } + + /// + /// 动作鉴权 + /// + /// + /// + public override void OnActionExecuting(ActionExecutingContext context) + { + + var permissionHandler = ServiceLocatorModel.Instance.GetRequiredService(); + + var currentUser = ServiceLocatorModel.Instance.GetRequiredService(); + + + + var result = permissionHandler.IsPass(Permission, currentUser); + + if (!result) + { + throw new AuthException(message: "您无权限访问该接口"); + } + } + + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/Yi.Framework.Authentication.JwtBearer.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj similarity index 66% rename from Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/Yi.Framework.Authentication.JwtBearer.csproj rename to Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj index 7c552323..00bb5f5e 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Authentication.JwtBearer/Yi.Framework.Authentication.JwtBearer.csproj +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Yi.Framework.Auth.JwtBearer.csproj @@ -6,8 +6,13 @@ enable + + + + + diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs new file mode 100644 index 00000000..dd8608b6 --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using StartupModules; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Auth.JwtBearer.Authentication; +using Yi.Framework.Auth.JwtBearer.Authentication.Options; +using Yi.Framework.Auth.JwtBearer.Authorization; +using Yi.Framework.Core; +using Yi.Framework.Core.Attributes; +using Yi.Framework.Core.Configuration; + +namespace Yi.Framework.Auth.JwtBearer +{ + [DependsOn(typeof(YiFrameworkCoreModule))] + public class YiFrameworkAuthJwtBearerModule : IStartupModule + { + public void Configure(IApplicationBuilder app, ConfigureMiddlewareContext context) + { + } + + public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) + { + services.Configure(Appsettings.appConfiguration("JwtTokenOptions")); + services.AddAuthentication(YiJwtAuthenticationHandler.YiJwtSchemeName); + services.AddTransient(); + services.AddSingleton(); + services.AddAuthentication(option => + { + option.AddScheme(YiJwtAuthenticationHandler.YiJwtSchemeName, YiJwtAuthenticationHandler.YiJwtSchemeName); + }); + services.AddSingleton(_=>new PermissionAttribute(string.Empty)); + services.AddControllers(options => { + options.Filters.Add(); + }); + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs new file mode 100644 index 00000000..850293ac --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Const/TokenTypeConst.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Core.Const +{ + public class TokenTypeConst + { + public const string Id = nameof(Id); + + public const string UserName= nameof(UserName); + + public const string TenantId = nameof(TenantId); + + public const string Email = nameof(Email); + + public const string PhoneNumber = nameof(PhoneNumber); + + public const string Roles = nameof(Roles); + + public const string Permission = nameof(Permission); + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/CurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs similarity index 94% rename from Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/CurrentUser.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs index cc24158f..9ca4688c 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/CurrentUser.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/CurrentUser.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Yi.Framework.Core.CurrentUser +namespace Yi.Framework.Core.CurrentUsers { public class CurrentUser : ICurrentUser { diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/ICurrentUser.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs similarity index 93% rename from Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/ICurrentUser.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs index 609a296e..d70a0d1f 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUser/ICurrentUser.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/CurrentUsers/ICurrentUser.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Yi.Framework.Core.CurrentUser +namespace Yi.Framework.Core.CurrentUsers { public interface ICurrentUser { diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs new file mode 100644 index 00000000..8ce9561d --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Exceptions/AuthException.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Core.Enums; + +namespace Yi.Framework.Core.Exceptions +{ + public class AuthException : Exception, + IHasErrorCode, + IHasErrorDetails, + IHasLogLevel + { + public ResultCodeEnum Code { get; set; } + + public string? Details { get; set; } + + public LogLevel LogLevel { get; set; } + + public AuthException( + ResultCodeEnum code = ResultCodeEnum.NoPermission, + string? message = null, + string? details = null, + Exception? innerException = null, + LogLevel logLevel = LogLevel.Warning) + : base(message, innerException) + { + Code = code; + Details = details; + LogLevel = logLevel; + } + + /// + /// 序列化参数的构造函数 + /// + public AuthException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + + public AuthException WithData(string name, object value) + { + Data[name] = value; + return this; + } + + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/CurrentUserExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/CurrentUserExtensions.cs index 23621cc6..9ea41d3f 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/CurrentUserExtensions.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Extensions/CurrentUserExtensions.cs @@ -9,7 +9,8 @@ using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; -using Yi.Framework.Core.CurrentUser; +using Yi.Framework.Core.Const; +using Yi.Framework.Core.CurrentUsers; namespace Yi.Framework.Core.Extensions { @@ -17,7 +18,7 @@ namespace Yi.Framework.Core.Extensions { public static IServiceCollection AddCurrentUserServer(this IServiceCollection services) { - return services.AddScoped(); + return services.AddScoped(); } @@ -51,10 +52,10 @@ namespace Yi.Framework.Core.Extensions var claims = authenticateContext.Principal.Claims; //通过鉴权之后,开始赋值 _currentUser.IsAuthenticated = true; - //_currentUser.Id = claims.GetClaim(JwtRegisteredClaimNames.Sid) is null ? 0 : Convert.ToInt64(claims.GetClaim(JwtRegisteredClaimNames.Sid)); - //_currentUser.UserName = claims.GetClaim(SystemConst.UserName) ?? ""; - //_currentUser.Permission = claims.GetClaims(SystemConst.PermissionClaim); - //_currentUser.TenantId = claims.GetClaim(SystemConst.TenantId) is null ? null : Guid.Parse(claims.GetClaim(SystemConst.TenantId)!); + _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); } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs index a3663574..297b7e6d 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/Model/ServiceLocatorModel.cs @@ -8,7 +8,7 @@ namespace Yi.Framework.Core.Model { public static class ServiceLocatorModel { - public static IServiceProvider? Instance { get; set; } + public static IServiceProvider Instance { get; set; } } } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs index 8881e06a..c284056d 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Core/YiFrameworkCoreModule.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Yi.Framework.Core.Configuration; +using Yi.Framework.Core.CurrentUsers; using Yi.Framework.Core.Extensions; using Yi.Framework.Core.Model; @@ -22,6 +23,8 @@ namespace Yi.Framework.Core //全局错误,需要靠前,放在此处无效 //app.UseErrorHandlingServer(); + + app.UseCurrentUserServer(); } public void ConfigureServices(IServiceCollection services, ConfigureServicesContext context) @@ -31,6 +34,7 @@ namespace Yi.Framework.Core //全盘扫描,自动依赖注入 services.AddAutoIocServer(); + services.AddCurrentUserServer(); //全局日志 GobalLogModel.SqlLogEnable = Appsettings.appBool("SqlLog_Enable"); GobalLogModel.LoginCodeEnable = Appsettings.appBool("LoginCode_Enable"); diff --git a/Yi.Framework.Net6/Yi.Framework.Data/Class1.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Class1.cs similarity index 100% rename from Yi.Framework.Net6/Yi.Framework.Data/Class1.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Data/Class1.cs diff --git a/Yi.Framework.Net6/Yi.Framework.Data/DataFilter.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataFilter.cs similarity index 100% rename from Yi.Framework.Net6/Yi.Framework.Data/DataFilter.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Data/DataFilter.cs diff --git a/Yi.Framework.Net6/Yi.Framework.Data/IDataFilter.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/IDataFilter.cs similarity index 100% rename from Yi.Framework.Net6/Yi.Framework.Data/IDataFilter.cs rename to Yi.Framework.Net6/src/framework/Yi.Framework.Data/IDataFilter.cs diff --git a/Yi.Framework.Net6/Yi.Framework.Data/Yi.Framework.Data.csproj b/Yi.Framework.Net6/src/framework/Yi.Framework.Data/Yi.Framework.Data.csproj similarity index 100% rename from Yi.Framework.Net6/Yi.Framework.Data/Yi.Framework.Data.csproj rename to Yi.Framework.Net6/src/framework/Yi.Framework.Data/Yi.Framework.Data.csproj diff --git a/Yi.Framework.Net6/test/Yi.Framework.Application/ApplicationSwaggerDoc.xml b/Yi.Framework.Net6/test/Yi.Framework.Application/ApplicationSwaggerDoc.xml index 54b66b5e..89050e60 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Application/ApplicationSwaggerDoc.xml +++ b/Yi.Framework.Net6/test/Yi.Framework.Application/ApplicationSwaggerDoc.xml @@ -9,6 +9,12 @@ 服务实现 + + + 测试token + + + Uow diff --git a/Yi.Framework.Net6/test/Yi.Framework.Application/Student/StudentService.cs b/Yi.Framework.Net6/test/Yi.Framework.Application/Student/StudentService.cs index 15f1354b..4a3c8d88 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Application/Student/StudentService.cs +++ b/Yi.Framework.Net6/test/Yi.Framework.Application/Student/StudentService.cs @@ -16,6 +16,11 @@ using Yi.Framework.Ddd.Services; using Yi.Framework.Core.Attributes; using Yi.Framework.Uow; using Microsoft.AspNetCore.Authorization; +using Yi.Framework.Auth.JwtBearer.Authentication; +using Yi.Framework.Core.Const; +using Yi.Framework.Core.CurrentUsers; +using Yi.Framework.Auth.JwtBearer.Authorization; +using Yi.Framework.Domain.Shared.Student.ConstClasses; namespace Yi.Framework.Application.Student { @@ -29,22 +34,37 @@ namespace Yi.Framework.Application.Student { private readonly IStudentRepository _studentRepository; private readonly StudentManager _studentManager; - //private readonly IUnitOfWorkManager _unitOfWorkManager; - public StudentService(IStudentRepository studentRepository, StudentManager studentManager, IUnitOfWorkManager unitOfWorkManager) + private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly JwtTokenManager _jwtTokenManager; + private readonly ICurrentUser _currentUser; + public StudentService(IStudentRepository studentRepository, StudentManager studentManager, IUnitOfWorkManager unitOfWorkManager, JwtTokenManager jwtTokenManager, ICurrentUser currentUser) { _studentRepository = studentRepository; _studentManager = studentManager; _unitOfWorkManager = unitOfWorkManager; + _jwtTokenManager = jwtTokenManager; + _currentUser=currentUser; + } + + /// + /// 测试token + /// + /// + public string GetToken() + { + var claimDic = new Dictionary() { { TokenTypeConst.Id, "123" }, { TokenTypeConst.UserName, "cc" } }; + return _jwtTokenManager.CreateToken(claimDic); } - private readonly IUnitOfWorkManager _unitOfWorkManager; /// /// Uow /// /// [Authorize] + [Permission(AuthStudentConst.查询)] public async Task PostUow() { + var o= _currentUser; StudentGetOutputDto res = new(); using (var uow = _unitOfWorkManager.CreateContext()) { diff --git a/Yi.Framework.Net6/test/Yi.Framework.Application/Yi.Framework.Application.csproj b/Yi.Framework.Net6/test/Yi.Framework.Application/Yi.Framework.Application.csproj index 5d913a96..c855a33c 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Application/Yi.Framework.Application.csproj +++ b/Yi.Framework.Net6/test/Yi.Framework.Application/Yi.Framework.Application.csproj @@ -9,6 +9,7 @@ + diff --git a/Yi.Framework.Net6/test/Yi.Framework.Application/YiFrameworkApplicationModule.cs b/Yi.Framework.Net6/test/Yi.Framework.Application/YiFrameworkApplicationModule.cs index fc405090..f1779cf9 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Application/YiFrameworkApplicationModule.cs +++ b/Yi.Framework.Net6/test/Yi.Framework.Application/YiFrameworkApplicationModule.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Yi.Framework.Application.Contracts; using Yi.Framework.Application.Contracts.Student; using Yi.Framework.Application.Student; +using Yi.Framework.Auth.JwtBearer; using Yi.Framework.Core.Attributes; using Yi.Framework.Domain; @@ -16,7 +17,8 @@ namespace Yi.Framework.Application { [DependsOn( typeof(YiFrameworkApplicationContractsModule), - typeof(YiFrameworkDomainModule) + typeof(YiFrameworkDomainModule), + typeof(YiFrameworkAuthJwtBearerModule) )] public class YiFrameworkApplicationModule : IStartupModule { diff --git a/Yi.Framework.Net6/test/Yi.Framework.Domain.Shared/Student/ConstClasses/AuthStudentConst.cs b/Yi.Framework.Net6/test/Yi.Framework.Domain.Shared/Student/ConstClasses/AuthStudentConst.cs new file mode 100644 index 00000000..5f3849af --- /dev/null +++ b/Yi.Framework.Net6/test/Yi.Framework.Domain.Shared/Student/ConstClasses/AuthStudentConst.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Domain.Shared.Student.ConstClasses +{ + public class AuthStudentConst + { + public const string 查询 = "student:student:list"; + public const string 添加 = "student:student:add"; + } +} diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/Program.cs b/Yi.Framework.Net6/test/Yi.Framework.Web/Program.cs index e5b27fbd..d5053ec2 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Web/Program.cs +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/Program.cs @@ -1,5 +1,4 @@ using AspNetCore.Microsoft.AspNetCore.Hosting; -using Yi.Framework.Authentication.JwtBearer; using Yi.Framework.Core.Autofac.Extensions; using Yi.Framework.Core.Autofac.Modules; using Yi.Framework.Core.Extensions; @@ -14,12 +13,7 @@ builder.WebHost.UseStartUrlsServer(builder.Configuration); //ģ builder.UseYiModules(typeof(YiFrameworkWebModule)); -builder.Services.AddAuthentication(YiJwtAuthenticationHandler.YiJwtSchemeName); -builder.Services.AddAuthentication(option => -{ - option.AddScheme(YiJwtAuthenticationHandler.YiJwtSchemeName, YiJwtAuthenticationHandler.YiJwtSchemeName); -}); //autofacģ,Ҫģ builder.Host.ConfigureAutoFacContainer(container => { diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/TimeTest.txt b/Yi.Framework.Net6/test/Yi.Framework.Web/TimeTest.txt index f4cd8375..7352107d 100644 Binary files a/Yi.Framework.Net6/test/Yi.Framework.Web/TimeTest.txt and b/Yi.Framework.Net6/test/Yi.Framework.Web/TimeTest.txt differ diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/Yi.Framework.Web.csproj b/Yi.Framework.Net6/test/Yi.Framework.Web/Yi.Framework.Web.csproj index 110113fb..46685d9b 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Web/Yi.Framework.Web.csproj +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/Yi.Framework.Web.csproj @@ -7,10 +7,18 @@ - + + + Always + + + Always + + + diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/YiFrameworkWebModule.cs b/Yi.Framework.Net6/test/Yi.Framework.Web/YiFrameworkWebModule.cs index 0ef22a8e..08e3ca9c 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Web/YiFrameworkWebModule.cs +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/YiFrameworkWebModule.cs @@ -1,6 +1,7 @@ using AspNetCore.Microsoft.AspNetCore.Builder; using StartupModules; using Yi.Framework.Application; +using Yi.Framework.Auth.JwtBearer; using Yi.Framework.Core; using Yi.Framework.Core.Attributes; using Yi.Framework.Sqlsugar; diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/appsettings.json b/Yi.Framework.Net6/test/Yi.Framework.Web/appsettings.json index 6b802969..c78daa1d 100644 --- a/Yi.Framework.Net6/test/Yi.Framework.Web/appsettings.json +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/appsettings.json @@ -25,5 +25,14 @@ "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //mysql "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //sqlserver ] + }, + + "JwtTokenOptions": { + "Audience": "yi", + "Issuer": "localhost:19002", + "Subject": "yiframwork", + "ExpSecond": 3600 + + } } diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/key.pem b/Yi.Framework.Net6/test/Yi.Framework.Web/key.pem new file mode 100644 index 00000000..3314ab6e --- /dev/null +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7VJTUt9Us8cKj +MzEfYyjiWA4R4/M2bS1GB4t7NXp98C3SC6dVMvDuictGeurT8jNbvJZHtCSuYEvu +NMoSfm76oqFvAp8Gy0iz5sxjZmSnXyCdPEovGhLa0VzMaQ8s+CLOyS56YyCFGeJZ +qgtzJ6GR3eqoYSW9b9UMvkBpZODSctWSNGj3P7jRFDO5VoTwCQAWbFnOjDfH5Ulg +p2PKSQnSJP3AJLQNFNe7br1XbrhV//eO+t51mIpGSDCUv3E0DDFcWDTH9cXDTTlR +ZVEiR2BwpZOOkE/Z0/BVnhZYL71oZV34bKfWjQIt6V/isSMahdsAASACp4ZTGtwi +VuNd9tybAgMBAAECggEBAKTmjaS6tkK8BlPXClTQ2vpz/N6uxDeS35mXpqasqskV +laAidgg/sWqpjXDbXr93otIMLlWsM+X0CqMDgSXKejLS2jx4GDjI1ZTXg++0AMJ8 +sJ74pWzVDOfmCEQ/7wXs3+cbnXhKriO8Z036q92Qc1+N87SI38nkGa0ABH9CN83H +mQqt4fB7UdHzuIRe/me2PGhIq5ZBzj6h3BpoPGzEP+x3l9YmK8t/1cN0pqI+dQwY +dgfGjackLu/2qH80MCF7IyQaseZUOJyKrCLtSD/Iixv/hzDEUPfOCjFDgTpzf3cw +ta8+oE4wHCo1iI1/4TlPkwmXx4qSXtmw4aQPz7IDQvECgYEA8KNThCO2gsC2I9PQ +DM/8Cw0O983WCDY+oi+7JPiNAJwv5DYBqEZB1QYdj06YD16XlC/HAZMsMku1na2T +N0driwenQQWzoev3g2S7gRDoS/FCJSI3jJ+kjgtaA7Qmzlgk1TxODN+G1H91HW7t +0l7VnL27IWyYo2qRRK3jzxqUiPUCgYEAx0oQs2reBQGMVZnApD1jeq7n4MvNLcPv +t8b/eU9iUv6Y4Mj0Suo/AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDU +AhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn//LiH1B3rXhcdyo3/vIttEk +48RakUKClU8CgYEAzV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD/ISL +DY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnK +xt1Il2HgxOBvbhOT+9in1BzA+YJ99UzC85O0Qz06A+CmtHEy4aZ2kj5hHjECgYEA +mNS4+A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2+cwPLhPIzIuwytXywh +2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfz +et6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEsCgYAnM3DQf3FJoSnXaMhr +VBIovic5l0xFkEHskAjFTevO86Fsz1C2aSeRKSqGFoOQ0tmJzBEs1R6KqnHInicD +TQrKhArgLXX4v3CddjfTRJkFWDbE/CkvKZNOrcf1nhaGCPspRJj2KUkj1Fhl9Cnc +dn/RsYEONbwQSjIfMPkvxF+8HQ== +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/public.pem b/Yi.Framework.Net6/test/Yi.Framework.Web/public.pem new file mode 100644 index 00000000..1c9b622d --- /dev/null +++ b/Yi.Framework.Net6/test/Yi.Framework.Web/public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo +4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u ++qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh +kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ +0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg +cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc +mwIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/Yi.Framework.Net6/test/Yi.Framework.Web/yi-sqlsugar-dev.db b/Yi.Framework.Net6/test/Yi.Framework.Web/yi-sqlsugar-dev.db index 0270e62e..b0514e4f 100644 Binary files a/Yi.Framework.Net6/test/Yi.Framework.Web/yi-sqlsugar-dev.db and b/Yi.Framework.Net6/test/Yi.Framework.Web/yi-sqlsugar-dev.db differ