ASP.NET Core 使用 Claim 认证
ASP.NET Core Web 应用下:
Program中:
#region 配置鉴权 { builder.Services.AddAuthentication(option => { option.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, option => { option.LogoutPath = "/Account/Login"; }); } #endregion
app.UseAuthentication();//鉴权
app.UseAuthorization(); //授权
登录验证结果:
[DataContract] [Serializable] public class LoginResult { /// <summary> /// 状态码 /// </summary> [DataMember(Name = "statusCode", Order = 2)] public int StatusCode { get; set; } /// <summary> /// 是否访问成功 /// </summary> [DataMember(Name = "isSuccessful", Order = 1)] public bool IsSuccess { get; set; } /// <summary> /// 系统返回状态说明 /// </summary> [DataMember(Name = "message", Order = 3)] public string? Message { get; set; } /// <summary> /// 返回的页面 /// </summary> [DataMember(Name = "returnUrl", Order = 4)] public string? ReturnUrl { get; set; } }
登录验证:
[HttpPost] public JsonResult JsonLogin(string username, string password, string num) { var result = new LoginResult(); result.IsSuccess = true; result.StatusCode = 200; result.Message = ""; string cnum = HttpContext.Session.GetString("ValidateCode") == null ? "" : HttpContext.Session.GetString("ValidateCode"); if (string.IsNullOrEmpty(num) || num.ToLower() != cnum.ToLower()) { result.StatusCode = 401; result.Message = "验证码错误"; return Json(result); } if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { result.StatusCode = 402; result.Message = "账号或密码不能为空"; return Json(result); } var pass = Helper.GetMd5Str(password); var old = _manager.Login(username, pass); if (old == null) { result.Message = "账号密码错误"; result.StatusCode = 403; return Json(result); } else { if (!old.IsUse) { result.Message = "账号停用"; result.StatusCode = 404; return Json(result); } var claims = new List<Claim>()//鉴别你是谁,相关信息 { new Claim("uid",old.ManagerId.ToString()), new Claim(ClaimTypes.Role,old.Role.RoleName), new Claim(ClaimTypes.Role,"Manager"), new Claim(ClaimTypes.Name,$"Manager_INFO"), //new Claim(ClaimTypes.Email,$"1234@163.com"), //new Claim("password",password),//可以写入任意数据 //new Claim("Account",old.LoginName), new Claim("NikeName",old.NikeName), new Claim("role",old.Role.RoleName) }; ClaimsPrincipal userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Manager")); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties { ExpiresUtc = DateTime.UtcNow.AddMinutes(30),//过期时间:30分钟 }).Wait(); return Json(result); } }
我们可以通过在 Controller 上或 Action 上增加 [Authorize] 标记 或 [AllowAnonymous] 标记,来控制用户对具体 Controller 或 Action 的访问,这跟以前的 Forms 认证的控制方式一模一样。
[Authorize] 标记:
表示必须拥有 Claim 的 Cookie 才能访问,否则就会跳转到指定的页面,我们一般指定跳转到登录页面。可以放到 Controller 或 Action 上。如果该标记添加到 Controller 上,则该 Controller 下的所有 Action 都会验证是否拥有 Claim 的 Cookie。
[AllowAnonymous] 标记:
表示允许匿名用户访问,没有登录也可以访问,也就是不需要 Claim 的 Cookie 就可以访问。可以放到 Controller 或 Action 上。通常的使用场景是:在 Controller 上放了 [Authorize] 之后,在该 Controller 下具体的一小部分 Action 上放 [AllowAnonymous] 标记。这样就保证 Controller 下只有一小部分 Action 允许未登录用户访问,其它的 Action 必须用户登录后才能访问。
[Authorize] public IActionResult Index() { var user = HttpContext.User; //user.Identity.Name //user.Identity.AuthenticationType StringBuilder sb = new StringBuilder(); // 遍历获取所有的存储信息 foreach (var cl in HttpContext.User.Claims) { sb.AppendLine($"{cl.Type}|{cl.Value}"); } _logger.LogInformation(sb.ToString()); // 通过便捷的方式获取登录的用户名 var a = User.Claims.FirstOrDefault(o => o.Type == "role")?.Value; return View(); }
User.Claims中的值
第一种
在view视图中将Claims转换成字典,这样就可以用键值的方式访问
@{
var currUser = User.Claims.ToDictionary(o => o.Type, o => o.Value);
}
@currUser.GetValueOrDefault("Manager")
注:RealName区分大小写
第二种 通过claims的linq查询
@User.Claims.FirstOrDefault(o => o.Type == "Manager")?.Value
注:字符串区分大小写;加问号?的意思是避免为空抛出异常,这里很巧妙。
第三种 通过User的方法
@User.FindFirstValue("Manager") 或 @User.FindFirst("Manager")?.Value
注:不区分大小写;注意问号的用法
综上所述:推荐使用第三种,很简略,另外读取系统ClaimTypes.Role注意引用相对应的命名空间:@using System.Security.Claims;
ASP.NET Core 网站使用 Claim 认证,实现用户登录,访问时进行身份验证方案,已经介绍完了。如果你想要快速搭建轻量级网站应用的话,使用 Claim 认证方式是一种非常方便快速的方案。
但是不建议在大中型项目中使用,还是采用主流的 token + redis 的方案实现用户登录认证比较好,原因如下:
- 后续项目肯定会涉及到各个系统之间的统一认证对接,以及与第三方的单点登录对接,这种情景使用 token + redis 的方案比较灵活简单,采用 Cookie 的实现方式比较麻烦。
- 对于用户请求负载均衡分发的场景,token + redis 的方案是非常好的方案,因为其天然保证所有请求都是无状态的,不需要在负载均衡服务器上配置会话保持,这样负载均衡服务器就可以根据每台应用服务器的负载状况,随意使用任何负载请求分发策略。
- 对于负载均衡来说, Claim 认证方案就不够灵活了,因为其 Cookie 只能在具体的服务器上进行加解密,从而识别登录用户。如果新的请求被负载均衡服务器分发到另一台应用服务器的话,那么就无法解密 Cookie 从而导致需要频繁重新登录,无法使用网站。只有在负载均衡服务器上配置会话保持,从而实现在一定的时间内将来自同一 ip 的请求分发到固定的应用服务器上,才能解决问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)