ASP.NET Core 中使用Cookie中间件

ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分配到HttpContext对象的User属性中。如果你想提供自己的登录方式和用户数据你可以使用Cookie中间件来实现独立的功能。

添加和配置

第一步是增加Cookie中间件到你的应用中。首先使用nuget增加Microsoft.AspNetCore.Authentication.Cookies 程序包。然后添加下面的几行代码到Startup.cs文件的Configure方法中,且要在app.UseMvc()之前。

  1. app.UseCookieAuthentication(new CookieAuthenticationOptions()
  2. {
  3. AuthenticationScheme = "MyCookieMiddlewareInstance",
  4. LoginPath = new PathString("/Account/Unauthorized/"),
  5. AccessDeniedPath = new PathString("/Account/Forbidden/"),
  6. AutomaticAuthenticate = true,
  7. AutomaticChallenge = true
  8. });

上面的代码片段配置了一下几个选项;

  1. 认证方案:这是一个已知中间件的值,当有多个实例的中间件如果你想限制授权到一个实例时这个选项将会起作用。
  2. 登录路径:这是当用户试图访问资源但未经过身份验证时,程序将会将请求重定向到这个相对路径。
  3. 禁止访问路径:当用户试图访问资源时,但未通过该资源的任何授权策略,请求将被重定向到这个相对路径。
  4. 自动认证:这个标志表明中间件应该会在每个请求上进行验证和重建他创建的序列化主体。
  5. 自动挑战:这个标志标明当中间件认证失败时应该重定向浏览器到登录路径或者禁止访问路径。

其他选项包括设置中间件所创建的声明的发行者,中间件存储的cookie名称,Cookie的域和cookie上的各种安全属性。默认情况下Cookie中间件将使用适当的安全选项,设置HTTPONLY避免cookie在客户端被JavaScript操作。当请求方式为HTTPS时限制Cookie的HTTPS操作。

创建Cookie

创建Cookie保存自己的信息,必须要初始化一个ClaimsPrincipal(类型)来序列化和保存你想保存的用户信息到Cookie中。每一次的方法调用都会在你的Controller(控制器)中有一个合适的ClaimsPrincipal对象。

  1. await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);

上面的代码将会创建一个加密的Cookie并且增加到当前的请求响应中。AuthenticationScheme明确规定在配置期间

退出

退出当前用户的登录,删除登录的cookie信息,可以在控制器中调用下面的方法。

  1. await HttpContext.Authentication.SignOutAsync("MyCookieMiddlewareInstance");

响应后端的变化

警告
一旦cookie创建就会成为身份单一认证的来源,即使在后台系统已经不可用,中间件也是不知道的,并且始终保持登录直到cookie失效。

Cookie认证中间件在他的选项类中提供了一系列的事件,其中 ValidateAsync() 事件可以用来中断和重写cookie认证的验证方法。

考虑到后台用户的数据库中可能会有‘最后的修改时间’这一列,为了在数据库修改之后你可以废止当前的Cookie,第一当创建这个Cookie时添加一个最后修改的声明并包含当前的值,当数据库中的数据改变时,这个值也同时更新。

实现一个ValidateAsync()的事件重写你必须写一个具有如下签名的方法。

  1. Task ValidateAsync(CookieValidatePrincipalContext context);

ASP.NET Core 认证在SecurityStampValidator中实现了这个验证。下面是一个类似的例子:

  1. public static class LastChangedValidator
  2. {
  3. public static async Task ValidateAsync(CookieValidatePrincipalContext context)
  4. {
  5. // Pull database from registered DI services.
  6. var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
  7. var userPrincipal = context.Principal;
  8.  
  9. // Look for the last changed claim.
  10. string lastChanged;
  11. lastChanged = (from c in userPrincipal.Claims
  12. where c.Type == "LastUpdated"
  13. select c.Value).FirstOrDefault();
  14.  
  15. if (string.IsNullOrEmpty(lastChanged) ||
  16. !userRepository.ValidateLastChanged(userPrincipal, lastChanged))
  17. {
  18. context.RejectPrincipal();
  19. await context.HttpContext.Authentication.SignOutAsync("MyCookieMiddlewareInstance");
  20. }
  21. }
  22. }

这些要在Cookie中间件配置时进行注册

  1. app.UseCookieAuthentication(options =>
  2. {
  3. options.Events = new CookieAuthenticationEvents
  4. {
  5. // Set other options
  6. OnValidatePrincipal = LastChangedValidator.ValidateAsync
  7. };
  8. });

如果你想非破坏性的更新用户主体,例如,name更新了,要想以不影响安全的方式你可以调用context.ReplacePrincipal() 并且设置 context.ShouldRenew 为 true

控制Cookie选项

CookieAuthenticationOptions 配备了各种各样的配置选项是你能够很好的调节创建的Cookie。

  • ClaimsIssuer - 被用来在任何中间件创建的属性之上。(看不懂)

  • CookieDomain - 如果cookie domain被设置为 ** .http://contoso.com** 那么contoso.com,http://www.contoso.com,staging.contoso.com 等等类似这样的域名也会被允许。

  • CookieHttpOnly - 这个标志指示这个 cookie 只会被服务端访问。默认值是true,修改这个属性将会开放你的应用造成 Cookie 盗窃,造成跨站脚本的bug。

  • CookiePath - 这个可以用来隔离运行在同一个 host 下的应用。如果你有一个应用运行在/app1 上,并且想限制 cookie 限制仅仅被发送给自己,那么你应该设置 CookiePath 属性为 /app1 ;Cookie将会明白只适用于道 /app1 或者他下面的请求。

  • ExpireTimeSpan - 这个 TimeSpan 时间段之后 Cookie 将会过期。

  • SlidingExpiration - 这个标志标记了如果超过了过期时间的一半后被访问那么Cookie将会被重置。新的过期时间将会后移到当前时间加上ExpireTimespan之后。当调用SignInAsync时可以通过 ** AuthenticationProperties ** 设置绝对的过期时间。通过限制验证cookie有效的时间,绝对期满可以提高应用程序的安全性。

持续性Cookie和绝对过期时间

您可能希望通过浏览器会话使cookie过期。也许你也想通过绝对过期时间和认证来结束cookie,那么你可以在登录认证和创建Cookie时使用HttpContext.Authentication.SignInAsync方法中的AuthenticationProperties参数类实现。AuthenticationProperties类在Microsoft.AspNetCore.Http.Authentication命名空间中。

例如

  1. await HttpContext.Authentication.SignInAsync(
  2. "MyCookieMiddlewareInstance",
  3. principal,
  4. new AuthenticationProperties
  5. {
  6. IsPersistent = true
  7. });

这个代码片段将会实现创建一个认证和相应的Cookie来实现即时浏览器关闭Cookie也能继续保留。任何在cookie属性中的过期时间的设置都将会保存下来。如果浏览器关闭时Cookie也过期了那么在重新启动浏览器是Cookie将会别清理。

  1. await HttpContext.Authentication.SignInAsync(
  2. "MyCookieMiddlewareInstance",
  3. principal,
  4. new AuthenticationProperties
  5. {
  6. ExpiresUtc = DateTime.UtcNow.AddMinutes()
  7. });

这段代码将创建一个身份认证和相应的cookie且将持续20分钟。 任何在Cookie options中配置的动态选项都会被忽略。 ExpiresUtc 和 IsPersistent 这两个属性是相互独立的。

其实上面bb了那么多,都没用! 不如来个demo

  1. // 1. 在Startup.cs的Configure方法中加上
  2. app.UseCookieAuthentication(new CookieAuthenticationOptions
  3. {
  4. AuthenticationScheme = "UserAuth",  // Cookie 验证方案名称,在写cookie时会用到。
  5. AutomaticAuthenticate = true,     // 是否自动启用验证,如果不启用,则即便客服端传输了Cookie信息,服务端也不会主动解析。除了明确配置了 [Authorize(ActiveAuthenticationSchemes = "上面的方案名")] 属性的地方,才会解析,此功能一般用在需要在同一应用中启用多种验证方案的时候。比如分Area.
  6. LoginPath = "/User/Index"     // 登录页
  7. });
  8.  
  9. // 2. 新建UserController
  10. // 3. 创建一个测试登录的方法(这里为了方便测是我用的是get方法,方便传参请求)
  11. public IActionResult Login(int userId, string userName)
  12. {
  13. WriteUser(userId, userName);
  14. return Content("Write");
  15. }
  16.  
  17. private async void WriteUser(int userId, string userName)
  18. {
  19. var identity = new ClaimsIdentity("Forms"); // 指定身份认证类型
  20. identity.AddClaim(new Claim(ClaimTypes.Sid, userId.ToString()));  // 用户Id
  21. identity.AddClaim(new Claim(ClaimTypes.Name, userName));       // 用户名称
  22. var principal = new ClaimsPrincipal(identity);
  23. await HttpContext.Authentication.SignInAsync("UserAuth", principal, new AuthenticationProperties { IsPersistent = true , ExpiresUtc = DateTime.UtcNow.AddMinutes() }); //过期时间20分钟
  24. }
  25.  
  26. // 4. 创建一个退出登录的方法
  27. public async Task<ActionResult> Logout()
  28. {
  29. await HttpContext.Authentication.SignOutAsync("UserAuth"); // Startup.cs中配置的验证方案名
  30. return RedirectToAction("User", "Index");
  31. }
  32.  
  33. // 5. 创建一个获取cookie用户信息的方法方便调用
  34. private int GetUserId()
  35. {
  36. //var userName = User.Identity.Name; //获取登录时存储的用户名称
  37. var userId = User.FindFirst(ClaimTypes.Sid).Value; // 获取登录时存储的Id
  38. if (string.IsNullOrEmpty(userId))
  39. {
  40. return ;
  41. }
  42. else
  43. {
  44. return int.Parse(userId);
  45. }
  46. }
  47. // 或者写一个测试Action
  48. public JsonResult CheckLogin()
  49. {
  50. var userName = User.Identity.Name; //获取登录时存储的用户名称
  51. var userId = User.FindFirst(ClaimTypes.Sid).Value; // 获取登录时存储的Id
  52. return Json({UserId:userId,UserName:userName});
  53. }
  54.  
  55. // 6. 以上是加密的方式如果直接写好像也是可以的
  56. HttpContext.Response.Cookies.Append("Key", "Value");

原文地址:https://zhuanlan.zhihu.com/p/24718122

官方文档地址:https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie

在ASP.NET Core 中使用Cookie中间件的更多相关文章

  1. 在ASP.NET Core 中使用Cookie中间件 (.net core 1.x适用)

    在ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分 ...

  2. ASP.NET CORE中使用Cookie身份认证

    大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...

  3. asp.net core中使用cookie身份验证

    配置 在 Startup.ConfigureServices 方法中,创建具有 AddAuthentication 和 AddCookie 方法的身份验证中间件服务: services.AddAuth ...

  4. asp.net core中写入自定义中间件

    首先要明确什么是中间件?微软官方解释:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?tabs=aspnet ...

  5. 在asp.net core中使用cookie认证

    以admin控制器为要认证的控制器举例 1.对控制器设置权限特性 //a 认证命名空间 using Microsoft.AspNetCore.Authorization; using Microsof ...

  6. 在ASP.NET Core中添加的Cookie如果含有特殊字符,会被自动转义

    我们知道在Cookie中有些字符是特殊字符,这些字符是不能出现在Cookie的键值中的. 比如"="是Cookie中用来分隔键和值的特殊字符,例如:Key01=Value01,表示 ...

  7. ASP.NET Core中的OWASP Top 10 十大风险-失效的访问控制与Session管理

    不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...

  8. ASP.NET Core 中的管道机制

    首先,很感谢在上篇文章 C# 管道式编程 中给我有小额捐助和点赞的朋友们,感谢你们的支持与肯定.希望我的每一次分享都能让彼此获得一些收获,当然如果我有些地方叙述的不正确或不当,还请不客气的指出.好了, ...

  9. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

随机推荐

  1. Spring + qyartz+多任务实现任务调度功能。

    前记:如果配置多个任务不能触发的请仔细检查配置文件!!!!!! 不存在多个同时间任务不能触发的现象!!!! 这个东西记得不要设置成false.如果写了就是true.不写的话默认true. 下面开始贴配 ...

  2. 用Caffe生成对抗样本

    同步自我的知乎专栏:https://zhuanlan.zhihu.com/p/26122612 上篇文章 瞎谈CNN:通过优化求解输入图像 - 知乎专栏 中提到过对抗样本,这篇算是针对对抗样本的一个小 ...

  3. [深入学习Redis]RedisAPI的原子性分析

    在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...

  4. 手机自动化测试:appium源码分析之bootstrap十六

    手机自动化测试:appium源码分析之bootstrap十六   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...

  5. UWP: 掌握编译型绑定 x:Bind

    在 UWP 开发中,我们在进行数据绑定时,除了可以使用传统的绑定 Binding,也可以使用全新的 x:Bind,由于后者是在程序编译时进行初始化操作(不同于 Binding,它是在运行时创建.初始化 ...

  6. Android报错:WindowManager$BadTokenException: Unable to add window -- window has already been added

    很久之前测试通过的代码,现在手机升级了Android7.0后一运行就崩溃,报出这样的错误,具体错误如下: Process: com.example.sho.android_anti_theft, PI ...

  7. 前端jquery validate表单验证框架的使用

    一.框架本身校验方法的扩展 建议写在页内用于扩展框架本身的一些校验方法, 使用频繁也可以直接在源码上修改 例如扩展手机号码的校验: /*手机号码验证扩展 最新的号码 mobile: class的表示 ...

  8. mac上使用使用rz,sz命令

    mac上使用rz,sz命令,mac上的终端不支持rz 和sz,所以安装iterm并配置使用rz和cz 1.首先需要下载安装iterm2,下载地址:下载后安装 http://www.iterm2.cn/ ...

  9. 跟着刚哥梳理java知识点——基本数据类型(三)

    1.8种基本数据类型 1)4种整数类型(byte.short.int.long) [知识点] 类型 存储空间 数值范围 byte 1字节=8位 -128-127 short 2字节 -2的15次方-2 ...

  10. ios UICollectionView简单说明

    原谅我记不住写下来好了 UICollectionViewFlowLayout 流式自动布局 继承于UICollectionViewLayout 初始化:[[UICollectionViewFlowLa ...