個人朋友問我cookie是什麼,用來幹什麼的,但是我竟然沒法清楚明白簡短地向其闡述cookie,這不由讓我陷入了沉思:爲何我沒法解釋清楚,我對學習的方法產生了懷疑!因此咱們在學習一個東西的時候,必定要作到知其然知其因此然。git
HTTP協議自己是無狀態的。什麼是無狀態呢,即服務器沒法判斷用戶身份。Cookie其實是一小段的文本信息)。客戶端向服務器發起請求,若是服務器須要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。github
打個比方,這就猶如你辦理了銀行卡,下次你去銀行辦業務,直接拿銀行卡就行,不須要身份證。web
廢話很少說,幹就完了,如今咱們建立ASP.NET Core MVC項目,撰寫該文章時使用的.NET Core SDK 3.0 構建的項目,建立完畢以後咱們無需安裝任何包,瀏覽器
可是咱們須要在Startup中添加一些配置,用於Cookie相關的。服務器
//public const string CookieScheme = "YourSchemeName"; public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //CookieAuthenticationDefaults.AuthenticationScheme Cookies Default Value //you can change scheme services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/LoginOrSignOut/Index/"; }); services.AddControllersWithViews(); // is able to also use other services. //services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, ConfigureMyCookie>(); }
在其中咱們配置登陸頁面,其中 AddAuthentication 中是咱們的方案名稱,這個是作什麼的呢?不少小夥伴都懵懵懂懂表示很懵逼啊,我看不少人也是都寫得默認,那它到底有啥用,通過我看AspNetCore源碼發現它這個是能夠作一些配置的。看下面的代碼:cookie
internal class ConfigureMyCookie : IConfigureNamedOptions<CookieAuthenticationOptions> { // You can inject services here public ConfigureMyCookie() {} public void Configure(string name, CookieAuthenticationOptions options) { // Only configure the schemes you want //if (name == Startup.CookieScheme) //{ // options.LoginPath = "/someotherpath"; //} } public void Configure(CookieAuthenticationOptions options) => Configure(Options.DefaultName, options); }
在其中你能夠定義某些策略,隨後你直接改變 CookieScheme 的變量就能夠替換某些配置,在配置中一共有這幾項,這無疑是幫助咱們快速使用Cookie的好幫手~點個贊。async
在源碼中能夠看到Cookie默認保存的時間是14天,這個時間咱們能夠去選擇,支持TimeSpan的那些類型。學習
public CookieAuthenticationOptions() { ExpireTimeSpan = TimeSpan.FromDays(14); ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter; SlidingExpiration = true; Events = new CookieAuthenticationEvents(); }
接下來LoginOrOut Controller,咱們模擬了登陸和退出,經過 SignInAsync 和 SignOutAsync 方法。網站
[HttpPost] public async Task<IActionResult> Login(LoginModel loginModel) { if (loginModel.Username == "haozi zhang" && loginModel.Password == "123456") { var claims = new List<Claim> { new Claim(ClaimTypes.Name, loginModel.Username) }; ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "login")); await HttpContext.SignInAsync(principal); //Just redirect to our index after logging in. return Redirect("/Home/Index"); } return View("Index"); } /// <summary> /// this action for web lagout /// </summary> [HttpGet] public IActionResult Logout() { Task.Run(async () => { //註銷登陸的用戶,至關於ASP.NET中的FormsAuthentication.SignOut await HttpContext.SignOutAsync(); }).Wait(); return View(); }
就拿出推出的源碼來看,其中獲取了Handler的某些信息,隨後將它轉換爲 IAuthenticationSignOutHandler 接口類型,這個接口 as 接口,像是在地方實現了這個接口,而後將某些運行時的值引用傳遞到該接口上。this
public virtual async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultSignOutSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignOutScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions)."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingSignOutHandlerException(scheme); } var signOutHandler = handler as IAuthenticationSignOutHandler; if (signOutHandler == null) { throw await CreateMismatchedSignOutHandlerException(scheme, handler); } await signOutHandler.SignOutAsync(properties); }
其中 GetHandlerAsync 中根據認證策略建立了某些實例,這裏再也不多說,由於源碼深不見底,我也說不太清楚...只是想表達一下看源碼的好處和壞處....
public async Task<IAuthenticationHandler> GetHandlerAsync(HttpContext context, string authenticationScheme) { if (_handlerMap.ContainsKey(authenticationScheme)) { return _handlerMap[authenticationScheme]; } var scheme = await Schemes.GetSchemeAsync(authenticationScheme); if (scheme == null) { return null; } var handler = (context.RequestServices.GetService(scheme.HandlerType) ?? ActivatorUtilities.CreateInstance(context.RequestServices, scheme.HandlerType)) as IAuthenticationHandler; if (handler != null) { await handler.InitializeAsync(scheme, context); _handlerMap[authenticationScheme] = handler; } return handler; }
最後咱們在頁面上想要獲取登陸的信息,能夠經過 HttpContext.User.Claims 中的簽名信息獲取。
@using Microsoft.AspNetCore.Authentication <h2>HttpContext.User.Claims</h2> <dl> @foreach (var claim in User.Claims) { <dt>@claim.Type</dt> <dd>@claim.Value</dd> } </dl> <h2>AuthenticationProperties</h2> <dl> @foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items) { <dt>@prop.Key</dt> <dd>@prop.Value</dd> } </dl>