添加UserAuthorizeAttribute:
/// <summary> /// 跳過屬性檢查 /// </summary> [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple =false,Inherited =true)] public sealed class SkipUserAuthorizeAttribute:Attribute,IFilterMetadata { } /// <summary> /// 用戶登錄驗證 /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UserAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter { public const string UserAuthenticationScheme = "UserAuthenticationScheme";//自定義一個默認的登錄方案 public UserAuthorizeAttribute() { this.AuthenticationSchemes = UserAuthenticationScheme; } public void OnAuthorization(AuthorizationFilterContext context) { //獲取登錄方案 var authenticate = context.HttpContext.AuthenticateAsync(UserAuthorizeAttribute.UserAuthenticationScheme); if (authenticate.Result.Succeeded || this.SkipUserAuthorize(context.ActionDescriptor)) { return; } HttpRequest httpRequest = context.HttpContext.Request; if(httpRequest.IsAjaxRequest())//ajax請求 { AjaxResult result = new AjaxResult(); result.Status = "redirect";//需要重定向 result.ErrorMsg = "登錄超時"; result.Data = ""; context.Result = new JsonResult(result); } else { RedirectResult redirectResult = new RedirectResult("~/Account/Login"); context.Result = redirectResult; } return; } protected virtual bool SkipUserAuthorize(ActionDescriptor actionDescriptor) { return actionDescriptor.FilterDescriptors .Where(a => a.Filter is SkipUserAuthorizeAttribute).Any(); } }
由於在ajax請求中需要做特殊判斷,這里自定義的IsAjaxRequst方法:
public static bool IsAjaxRequest(this HttpRequest request) { bool result = false; var xreq = request.Headers.ContainsKey("x-requested-with"); if (xreq) { result = request.Headers["x-requested-with"] == "XMLHttpRequest"; } return result; }
startup中注冊cookie:
#region 注冊cookie //注冊cookie認證服務 services.AddAuthentication(UserAuthorizeAttribute.UserAuthenticationScheme) .AddCookie(UserAuthorizeAttribute.UserAuthenticationScheme,options => { options.LoginPath = "/Account/Login"; options.LogoutPath = "/Account/Logout"; }); #endregion
action中檢查登錄:
[UserAuthorize] public IActionResult Index() { return View(); }
登陸后cookie的保存:
//登錄驗證成功后,admin=當前用戶
//Cookies //創建身份認證Cookie var claimIdentity = new ClaimsIdentity(UserAuthorizeAttribute.UserAuthenticationScheme); claimIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, admin.Id.ToString())); claimIdentity.AddClaim(new Claim(ClaimTypes.Name, admin.Name)); claimIdentity.AddClaim(new Claim("Account", model.Account)); claimIdentity.AddClaim(new Claim("Password", model.Password)); if (model.RememberMe == "on") { claimIdentity.AddClaim(new Claim("RememberMe", "on")); } else { claimIdentity.AddClaim(new Claim("RememberMe", "off")); } var claimsPrincipal = new ClaimsPrincipal(claimIdentity); HttpContext.SignInAsync(claimsPrincipal, new AuthenticationProperties { ExpiresUtc = DateTime.Now.AddDays(7),//有效時間1周 IsPersistent=true, AllowRefresh=false, });
需要取cookie的時候:
//獲取cookie中用戶信息 var adminAccount =HttpContext.User.Claims.SingleOrDefault(t=>t.Type=="Account"); string account = adminAccount == null ? "" : adminAccount.Value; var adminPwd = HttpContext.User.Claims.SingleOrDefault(t => t.Type == "Password"); string pwd = adminPwd == null ? "" : adminPwd.Value; var rememberMe = HttpContext.User.Claims.SingleOrDefault(t => t.Type == "RememberMe"); string rem = rememberMe == null ? "" : rememberMe.Value;
在view中,特別是layout中,比如要顯示用戶名,當然需要引入對應的命名空間:
<span>@User.Claims.SingleOrDefault(t=>t.Type== ClaimTypes.Name).Value</span>
至此,基本完成,可能還有缺陷,望您指正,感謝。
全部解析過程,參考大神的分享: