cookie认证方式如下图所示,当我们访问一个网页(Admin/Index)时候,这时候系统会检查你是否有权限,假如没有权限,便会我当前Url重定向到登陆页面(/Account/Login),在登陆成功后,系统会返回一个cookie保存在浏览器,此时再带
着这个cookie去重新访问你最开始要访问的页面(Admin/Index)。
我们在.net core 中,也有一套基于cookie-basic的认证方式。
配置文件:
"CookieOptions": { "CookieName": "Authentication", "CookieDomain": "xxxxxx.com", "CookieTimeout": "28800", "CookieLoginUrl": "/Auth/Login", "CookieLogoutUrl": "/Auth/Logout", "CookieDeniedUrl": "/Auth/Forbidden", "CookieReturnUrlParameter": "returnUrl", "CookieIsessential": true }
ConfigureService方法中添加:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(o => { var cookieOptions = Configuration.GetSection("CookieOptions").Get<CookieOptions>(); o.LoginPath = cookieOptions.CookieLoginUrl;//登录路径:这是当用户试图访问资源但未经过身份验证时,程序将会将请求重定向到这个相对路径。 o.LogoutPath = cookieOptions.CookieLogoutUrl; o.AccessDeniedPath = cookieOptions.CookieDeniedUrl; o.ReturnUrlParameter = cookieOptions.CookieReturnUrlParameter ?? "returnUrl"; double timeOut = Convert.ToDouble(cookieOptions.CookieTimeout ?? "28880"); o.ExpireTimeSpan = System.TimeSpan.FromSeconds(timeOut); o.Cookie.HttpOnly = true; o.Cookie.Name = cookieOptions.CookieName; o.Cookie.Domain = cookieOptions.CookieDomain; o.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax; o.Cookie.Path = "/"; o.Cookie.IsEssential = Convert.ToBoolean(cookieOptions.CookieIsessential ?? "true");//是否强制存储cookie,注意,也就是当用户不同意使用cookie的时候,你也可以通过设置这个属性为true把cookie强制存储. o.SlidingExpiration = true;//Cookie可以分为永久性的和临时性的。 临时性的是指只在当前浏览器进程里有效,浏览器一旦关闭就失效(被浏览器删除)。 永久性的是指Cookie指定了一个过期时间,在这个时间到达之前,此cookie一直有效(浏览器一直记录着此cookie的存在)。 slidingExpriation的作用是,指示浏览器把cookie作为永久性cookie存储,但是会自动更改过期时间,以使用户不会在登录后并一直活动,但是一段时间后却自动注销。也就是说,你10点登录了,服务器端设置的TimeOut为30分钟,如果slidingExpriation为false,那么10:30以后,你就必须重新登录。如果为true的话,你10:16分时打开了一个新页面,服务器就会通知浏览器,把过期时间修改为10:46。 更详细的说明还是参考MSDN的文档。 o.Events = new CookieAuthenticationEvents { OnSignedIn = context => { return Task.CompletedTask; }, OnSigningOut = context => { return Task.CompletedTask; }, OnValidatePrincipal = context => { return Task.CompletedTask; }, }; });
Configure方法中添加:
app.UseAuthentication();
助手类:
public class DefaultFormsAuthentication { /// <summary> /// 设置登录Cookie /// https://www.cnblogs.com/savorboard/p/authentication.html /// </summary> /// <param name="httpContext"></param> /// <param name="userPrincipal">登录人的用户身份证信息(身份证当事人)</param> /// <returns></returns> public static Task SetAuthCookieAsync(HttpContext httpContext, ClaimsPrincipal userPrincipal) { return httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal); } /// <summary> /// 设置登录Cookie /// </summary> /// <param name="httpContext"></param> /// <param name="userPrincipal">登录人的用户身份证信息(身份证当事人)</param> /// <param name="authenticationProperties">授权属性信息</param> /// <returns></returns> public static Task SetAuthCookieAsync(HttpContext httpContext, ClaimsPrincipal userPrincipal, AuthenticationProperties authenticationProperties) { //登入操作 return httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, authenticationProperties); } /// <summary> /// 设置登录Cookie /// </summary> /// <param name="httpContext"></param> /// <param name="userPrincipal">登录人的用户身份证信息(身份证当事人)</param> /// <param name="expireTimeSpan">Cookie过期时间</param> /// <returns></returns> public static Task SetAuthCookieAsync(HttpContext httpContext, ClaimsPrincipal userPrincipal, TimeSpan expireTimeSpan) { //登入操作 if (expireTimeSpan > TimeSpan.Zero) { return SetAuthCookieAsync( httpContext , userPrincipal , new AuthenticationProperties { ExpiresUtc = DateTimeOffset.UtcNow.Add(expireTimeSpan), IsPersistent = true,//若要创建持久 cookie,则还必须设置IsPersistent AllowRefresh = true, } ); } else { return SetAuthCookieAsync(httpContext, userPrincipal); } } /// <summary> /// 设置登录Cookie /// </summary> /// <param name="httpContext"></param> /// <param name="authUser">登录用户信息</param> /// <param name="expireTimeSpan">指定Cookie的过期时间</param> /// <returns></returns> public static Task SetAuthCookieAsync(HttpContext httpContext, LoginModel authUser, TimeSpan expireTimeSpan) { // 身份证当事人 ClaimsPrincipal userPrincipal = AuthenticationTicketBuilder.CreateAuthenticationTicket(authUser); //当事人登录 return SetAuthCookieAsync(httpContext, userPrincipal, expireTimeSpan); } /// <summary> /// 设置登录Cookie /// 默认使用全局ExpireTimeSpan设置的过期时间 /// </summary> /// <param name="httpContext"></param> /// <param name="authUser">登录用户信息</param> /// <returns></returns> public static Task SetAuthCookieAsync(HttpContext httpContext, LoginModel authUser) { // 身份证当事人 ClaimsPrincipal userPrincipal = AuthenticationTicketBuilder.CreateAuthenticationTicket(authUser); //当事人登录 return SetAuthCookieAsync(httpContext, userPrincipal); } /// <summary> /// 设置JWT格式的登录Cookie /// </summary> /// <param name="httpContext"></param> /// <param name="authUser">登录用户信息</param> /// <param name="jwtTokenGenerator">JWT Token生成器</param> /// <returns></returns> /* public static Task SetJwtAuthCookieAsync(HttpContext httpContext, LoginModule authUser, IJwtTokenGenerator jwtTokenGenerator) { return SetJwtAuthCookieAsync(httpContext, authUser, jwtTokenGenerator, TimeSpan.Zero); }*/ /// <summary> /// /// </summary> /// <param name="httpContext"></param> /// <param name="authUser"></param> /// <param name="jwtTokenGenerator"></param> /// <param name="expireTimeSpan"></param> /// <returns></returns> /* public static Task SetJwtAuthCookieAsync(HttpContext httpContext, LoginModule authUser, IJwtTokenGenerator jwtTokenGenerator, TimeSpan expireTimeSpan) { //创建登录用户身份单元项集合 var claimList = AuthenticationTicketBuilder.CreateClaimList(authUser); //身份证当事人 TokenWithClaimsPrincipal tokenWithClaimsPrincipal = jwtTokenGenerator.GenerateAccessTokenWithClaimsPrincipal(claimList); if (expireTimeSpan > TimeSpan.Zero) { tokenWithClaimsPrincipal.AuthenticationProperties.ExpiresUtc = CalculateCookieExpirationDate(expireTimeSpan); } //当事人登录 return SetAuthCookieAsync(httpContext, tokenWithClaimsPrincipal.ClaimsPrincipal, tokenWithClaimsPrincipal.AuthenticationProperties); }*/ /// <summary> /// 退出登录 /// </summary> public static Task Signout(HttpContext httpContext) { //登出操作 return httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); } #region net core 关于 cookie 序列化,加密,编码的方法 /// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static byte[] Serialize(AuthenticationTicket data) { return TicketSerializer.Default.Serialize(data); } /// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static AuthenticationTicket Deserialize(byte[] data) { return TicketSerializer.Default.Deserialize(data); } /// <summary> /// 获取登录用户票据信息(密文) /// https://www.cnblogs.com/savorboard/p/dotnetcore-data-protection.html /// </summary> /// <param name="provider"></param> /// <param name="plainTicket"></param> /// <returns></returns> public static string Encrypt(IDataProtector provider, string plainTicket) { return provider.Protect(plainTicket); } public static byte[] Encrypt(IDataProtector provider, byte[] plainTicket) { return provider.Protect(plainTicket); } /// <summary> /// 获取登录用户票据信息(明文) /// https://www.cnblogs.com/savorboard/p/dotnetcore-data-protection.html /// </summary> /// <param name="provider"></param> /// <param name="encryptedTicket"></param> /// <returns></returns> public static string Decrypt(IDataProtector provider, string encryptedTicket) { return provider.Unprotect(encryptedTicket); } public static byte[] Decrypt(IDataProtector provider, byte[] encryptedTicket) { return provider.Unprotect(encryptedTicket); } public static string Encode(byte[] data) { return Base64UrlTextEncoder.Encode(data); } public static byte[] Decode(string text) { return Base64UrlTextEncoder.Decode(text); } #endregion } public class AuthenticationTicketBuilder { /// <summary> /// 创建登录用户的身份单元项集合 /// </summary> /// <param name="authUser">登录用户信息</param> /// <returns>返回登陆用户的身份单元项集合</returns> public static List<Claim> CreateClaimList(LoginModel authUser) { //身份单元项项集合 List<Claim> claimList = new List<Claim>() { new Claim(type: ClaimTypes.Email, value: authUser.Email), //身份单元项 new Claim(type: ClaimTypes.Name, value: authUser.RealName), new Claim(type: ClaimTypes.NameIdentifier, value: authUser.ID.ToString()), new Claim(type: ClaimTypes.Role, value: authUser.ClientID ?? string.Empty), }; return claimList; } /// <summary> /// 创建登陆用户的票据信息 /// </summary> /// <param name="authUser">登录用户信息</param> /// <returns>返回登录用户的用户身份证信息(身份证当事人)</returns> public static ClaimsPrincipal CreateAuthenticationTicket(LoginModel authUser) { List<Claim> claimList = CreateClaimList(authUser);//身份单元项集合 return CreateAuthenticationTicket(claimList); } /// <summary> /// 创建登陆用户的票据信息 /// </summary> /// <param name="claimList">登陆用户的身份单元项集合</param> /// <returns>返回登录用户的用户身份证信息(身份证当事人)</returns> public static ClaimsPrincipal CreateAuthenticationTicket(IEnumerable<Claim> claimList) { ClaimsIdentity userIdentity = new ClaimsIdentity(claimList, "ticket");//身份证 ClaimsPrincipal userPrincipal = new ClaimsPrincipal(userIdentity);//身份证当事人 return userPrincipal; } }
LoginModel配置类:
public class LoginModel { public LoginModel() { } public LoginModel(string returnUrl) { this.ReturnUrl = returnUrl; } public LoginModel(string email, string password) { this.Email = email; this.Password = password; } public LoginModel(string email, string password, string returlUrl) : this(email, password) { this.ReturnUrl = returlUrl; } public int ID { get; set; } public string Email { get; set; } public string Password { get; set; } public string ReturnUrl { get; set; } public string ClientID { get; set; } public string RealName { get; set; } }
客户端:
//判断登录 _httpContext.User.Identity.IsAuthenticated; //设置登录 DefaultFormsAuthentication.SetAuthCookieAsync(this._httpContext, new LoginModel { ClientID = userInfo.UserID.ToString(), Email = "abc@qq.com", ID = "1", Password = string.Empty, RealName = "fan", ReturnUrl = string.Empty, });
111