zoukankan      html  css  js  c++  java
  • 三分钟学会在ASP.NET Core MVC 中使用Cookie

    一.Cookie是什么?

      我的朋友问我cookie是什么,用来干什么的,可是我居然无法清楚明白简短地向其阐述cookie,这不禁让我陷入了沉思:为什么我无法解释清楚,我对学习的方法产生了怀疑!所以我们在学习一个东西的时候,一定要做到知其然知其所以然。

      HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

      打个比方,这就犹如你办理了银行卡,下次你去银行办业务,直接拿银行卡就行,不需要身份证。

    二.在.NET Core中尝试

      废话不多说,干就完了,现在我们创建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源码发现它这个是可以做一些配置的。看下面的代码:

    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的好帮手~点个赞。


    在源码中可以看到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 接口,像是在地方实现了这个接口,然后将某些运行时的值引用传递到该接口上。

    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>

    三.最后效果以及源码地址

     GitHub地址:https://github.com/zaranetCore/aspNetCore_JsonwebToken/tree/master/src/Identity.Cookie/DotNetCore_Cookie_Sample

  • 相关阅读:
    Windows 7目录
    用wubi安装的Ubuntu在重装Windows 7系统后,如何恢复(转)
    用java查询HBase中某表的一批数据
    hbase数据模型以及编码压缩(转)
    应用Flume+HBase采集和存储日志数据
    HBase性能调优(转)
    【剑指Offer学习】【面试题50:树中两个结点的最低公共祖先】
    [Phonegap+Sencha Touch] 移动开发24 打包wp8.1的App,执行时输入框聚焦弹出软键盘之后,界面上移而不恢复原位的解决的方法
    写在课程设计之后
    String内存溢出异常(错误)可能的原因及解决方式
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/12099286.html
Copyright © 2011-2022 走看看