• ASP.NET Core-Cookie-based认证的实现


     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;
            }
        }
    View Code

    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; }
        }
    View Code

    客户端:

    //判断登录
    _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

  • 相关阅读:
    Response/Request
    每日总结-Day5
    每日总结-Day4
    每日总结-Day3
    每日总结-Day2
    每日总结-Day1
    day6
    Day5
    Day4
    需求分析之软件初设想
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12395700.html
Copyright © 2020-2023  润新知