/// <summary> /// 获取基于JWT的Token /// </summary> /// <param name="claims">需要在登陆的时候配置</param> /// <param name="requirement">在startup中定义的参数</param> /// <returns></returns> public static string IssueToken(Claim[] claims, AdmPolicyRequirement requirement) { var now = DateTime.Now; // 实例化JwtSecurityToken var jwt = new JwtSecurityToken( issuer: requirement.Issuer, audience: requirement.Audience, claims: claims, notBefore: now, expires: now.Add(requirement.Expiration), signingCredentials: requirement.SigningCredentials ); // 生成 Token return(new JwtSecurityTokenHandler().WriteToken(jwt));; }
public static AuthenticateInfo Get(LoginUserInfo user, AdmPolicyRequirement requirement, IDistributedCache cache = null) { var expirationSeconds = requirement.Expiration.TotalSeconds; var subjectId = user.Id.ToString(); var claims = new List <Claim> { new Claim(JwtRegisteredClaimNames.Sub, subjectId), new Claim(ClaimTypes.NameIdentifier, subjectId), new Claim(JwtRegisteredClaimNames.AuthTime, DateTime.Now.ToString()), //DateTime.UtcNow.ToString("o") new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(expirationSeconds).ToString()) }; if (!string.IsNullOrWhiteSpace(user.Name)) { claims.Add(new Claim(JwtClaimTypes.Name, user.Name)); } claims.AddRange(user.Roles.Select(s => new Claim(ClaimTypes.Role, s.Id.ToString()))); var token = JwtToken.IssueToken(claims.ToArray(), requirement); if (cache != null) { //token白名单 一个用户只有一个token有效 //需要启用AuthorizationSetup中代码 //30天清理失效得key cache.SetString(subjectId, token, new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromDays(30) }); } return(new AuthenticateInfo() { AccessToken = token, TokenType = "Bearer", ExpireInSeconds = expirationSeconds, UserName = user.UserName, IsMaster = user.IsMaster, Name = user.Name, UserId = user.Id, Roles = user.Roles }); }
public static void AddAuthorizationSetup(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } var secretKey = AdmBootsApp.Configuration["Authentication:JwtBearer:SecurityKey"]; var keyByteArray = Encoding.ASCII.GetBytes(secretKey); var signingKey = new SymmetricSecurityKey(keyByteArray); var issuer = AdmBootsApp.Configuration["Authentication:JwtBearer:Issuer"]; var audience = AdmBootsApp.Configuration["Authentication:JwtBearer:Audience"]; var admPolicyRequirement = new AdmPolicyRequirement( ClaimTypes.Role, //基于角色的授权 issuer, //发行人 audience, //订阅人 new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256), //签名凭据 expiration: TimeSpan.FromDays(1) //接口的过期时间 总的Token有效时间 = 接口的过期时间 + ClockSkew ); //复杂的策略授权 services.AddAuthorization(options => { options.AddPolicy(AdmConsts.POLICY, policy => policy.Requirements.Add(admPolicyRequirement)); }); //官方JWT认证 //开启Bearer认证 services.AddAuthentication(o => { o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; o.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme; }) // 添加JwtBearer服务 .AddJwtBearer(o => { //令牌验证参数 o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, ValidateIssuer = true, ValidIssuer = issuer, //发行人 ValidateAudience = true, ValidAudience = audience, //订阅人 ValidateLifetime = true, ClockSkew = TimeSpan.Zero, RequireExpirationTime = true, }; o.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { // 如果过期,则把<是否过期>添加到,返回头信息中 if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return(Task.CompletedTask); }, ////token白名单 一个用户只有一个token有效 //OnTokenValidated = context => { // var token = ((JwtSecurityToken)context.SecurityToken).RawData; // var uid = JwtToken.ReadJwtToken<int>(token); // var cache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>(); // if (cache.GetString(uid.ToString()) != token) { // context.Fail("token不在白名单中");//返回401 // } // return Task.CompletedTask; //}, //对连接到集线器的用户进行身份验证 SignalR //https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1 OnMessageReceived = context => { if (!context.HttpContext.Request.Path.HasValue) { return(Task.CompletedTask); } var accessToken = context.Request.Query["access_token"]; //判断是Signalr的路径 var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/api/chatHub"))) { context.Token = accessToken; } return(Task.CompletedTask); } }; }); // 注入权限处理器 services.AddScoped <IAuthorizationHandler, AdmAuthorizationHandler>(); services.AddSingleton(admPolicyRequirement); }
public LoginController(IUserService userService, AdmPolicyRequirement requirement, IDistributedCache cache) { _userService = userService; _requirement = requirement; _cache = cache; }