在身份認證中,如果某個Action需要許可權才能訪問,最開始的想法就是,哪個Action需要許可權才能訪問,我們寫個特性標註到上面即可,[TypeFilter(typeof(CustomAuthorizeActionFilterAttribute))] 當然了,要先在服務裡面使用Session的服務== ...
在身份認證中,如果某個Action需要許可權才能訪問,最開始的想法就是,哪個Action需要許可權才能訪問,我們寫個特性標註到上面即可,[TypeFilter(typeof(CustomAuthorizeActionFilterAttribute))]
/// <summary> /// 這是一個Action的Filter` 但是用作許可權驗證 /// </summary> public class CustomAuthorizeActionFilterAttribute : Attribute, IActionFilter { private ILogger<CustomAuthorizeActionFilterAttribute> _logger = null; public CustomAuthorizeActionFilterAttribute(ILogger<CustomAuthorizeActionFilterAttribute> logger) { this._logger = logger; } public void OnActionExecuting(ActionExecutingContext context) { //取出Session var strUser = context.HttpContext.Session.GetString("CurrentUser"); if (!string.IsNullOrWhiteSpace(strUser)) { CurrentUser currentUser = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrentUser>(strUser); _logger.LogDebug($"userName is {currentUser.Name}"); } else { context.Result = new RedirectResult("~/Fourth/Login"); } } public void OnActionExecuted(ActionExecutedContext context) { //context.HttpContext.Response.WriteAsync("ActionFilter Executed!"); Console.WriteLine("ActionFilter Executed!"); //this._logger.LogDebug("ActionFilter Executed!"); } }
當然了,要先在服務裡面使用Session的服務==》services.AddSession();
但是這樣不好。.Net Core框架下,有一個特性Authorize,當我們需要使用的時候,在某個Action上面標註即可
[Authorize] public IActionResult Center() { return Content("Center"); }
我們來運行看一下,會報異常
因為我們沒有使用服務,在.Net Core下麵,是預設不啟用授權過濾器的。這也是.Net Core框架的一個好處,我們需要的時候才進行使用。框架做的少,更輕。
下麵我們在服務裡面使用授權過濾器的服務
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme). AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { o.LoginPath = new PathString("/Home/Login"); });
再次瀏覽剛纔的頁面,這樣就會請求到登錄頁面,會把剛纔請求的頁面當做一個參數
當然也要使用app.UseAuthentication();這個中間件。
在.Net Core裡面,保存登錄狀態,也是通過Cookie的方式。使用ClaimsIdentity與ClaimsPrincipal
public ActionResult Login(string name, string password) { this._ilogger.LogDebug($"{name} {password} 登陸系統"); #region 這裡應該是要到資料庫中查詢驗證的 CurrentUser currentUser = new CurrentUser() { Id = 123, Name = "Bingle", Account = "Administrator", Password = "123456", Email = "[email protected]", LoginTime = DateTime.Now, Role = name.Equals("Bingle") ? "Admin" : "User" }; #endregion #region cookie { ////就很像一個CurrentUser,轉成一個claimIdentity var claimIdentity = new ClaimsIdentity("Cookie"); claimIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, currentUser.Id.ToString())); claimIdentity.AddClaim(new Claim(ClaimTypes.Name, currentUser.Name)); claimIdentity.AddClaim(new Claim(ClaimTypes.Email, currentUser.Email)); claimIdentity.AddClaim(new Claim(ClaimTypes.Role, currentUser.Role)); claimIdentity.AddClaim(new Claim(ClaimTypes.Sid, currentUser.Id.ToString())); var claimsPrincipal = new ClaimsPrincipal(claimIdentity); base.HttpContext.SignInAsync(claimsPrincipal).Wait();//不就是寫到cookie } #endregion return View(); }
再次進行登錄,我們就可以看到這樣一個Cookie
在這之後,我們再去訪問Genter頁面,發現還是和之前返回的結果一樣,還是訪問不到。這是為什麼呢?是因為我們在Action上面打的標簽[Authorize],什麼都沒給,我們做下修改
[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] public IActionResult Center() { return Content("Center"); }
現在我們再次進行訪問,發現就可以訪問成功了
通過User.FindFirstValue(ClaimTypes.Sid);這種方式,可以獲取到我們存入的值。
Scheme、Policy擴展
Scheme
#region 設置自己的schema的handler services.AddAuthenticationCore(options => options.AddScheme<MyHandler>("myScheme", "demo myScheme")); #endregion #region Schame 驗證 services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;// "Richard";// }) .AddCookie(options => { options.LoginPath = new PathString("/Fourth/Login");// 這裡指定如果驗證不通過就跳轉到這個頁面中去 options.ClaimsIssuer = "Cookie"; });
Policy
#region 支持 policy 認證授權的服務 // 指定通過策略驗證的策略列 services.AddSingleton<IAuthorizationHandler, AdvancedRequirement>(); services.AddAuthorization(options => { //AdvancedRequirement可以理解為一個別名 options.AddPolicy("AdvancedRequirement", policy => { policy.AddRequirements(new NameAuthorizationRequirement("1")); }); }).AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = new PathString("/Fourth/Login"); options.ClaimsIssuer = "Cookie"; }); #endregion
還需要在Configure方法中對中間件進行使用
app.UseSession(); app.UseCookiePolicy(); // app.UseAuthentication(); // 標識在當前系統中使用這個許可權認證