做英文网站的心得,大学生网站开发文档,网站编辑制作,wordpress怎样排版本文我们来探讨下JWT VS Session的问题#xff0c;我们可直接抛出问题#xff1a;使用客户端存储的JWT比服务端维持Session更好吗#xff1f; 既然要比较JWT VS Session#xff0c;那我们就得知道为何需要JWT和Session#xff0c;它们共同是为了解决什么问题呢#xff1f… 本文我们来探讨下JWT VS Session的问题我们可直接抛出问题使用客户端存储的JWT比服务端维持Session更好吗 既然要比较JWT VS Session那我们就得知道为何需要JWT和Session它们共同是为了解决什么问题呢那我们从一个场景说起网上购物现已是再平常不过的事情了当我们将某个商品加入购物车后然后跳转到其他商品页面此时需要之前选择的商品依然在购物车中此时就需要维持会话因为HTTP无状态所以JWT和Session共同点都是为了持久维持会话而存在为了克服HTTP无状态的情况JWT和Session分别是如何处理的呢JWT VS SessionSession当用户在应用系统中登录后此时服务端会创建一个Session我们也称作为会话然后SessionId会保存到用户的Cookie中只要用户是登录状态对于每个请求在Cookie中的SessionId都会发送到服务端然后服务端会将保存在内存中的SessionId和Cookie中的SessionId进行比较来认证用户的身份并响应。JWT当用户在应用系统中登录后此时服务端会创建一个JWT并将JWT发送到客户端客户端存储JWT一般是在Local Storage中同时在每个请求头即Authorization中包含JWT对于每个请求服务端都会进行验证JWT是否合法直接在服务端本地进行验证比如颁发者受理者等等以致于无需发出网络请求或与数据库交互这种方式可能比使用Session更快从而加快响应性能降低服务器和数据库服务器负载。通过如上对JWT认证和Session认证简短的描述我们知道二者最大的不同在于Session是存储在服务端而JWT存储在客户端。服务端存储会话无外乎两种一种是将会话标识符存储在数据库一种是存储在内存中维持会话我想大多数情况下都是基于内存来维持会话但是这会带来一定的问题如果系统存在大流量也就是说若有大量用户访问系统此时使用基于内存维持的会话则限制了水平扩展但对基于Token的认证则不存在这样的问题同时Cookie一般也只适用于单域或子域如果对于跨域假如是第三方Cookie浏览器可能会禁用Cookie所以也受浏览器限制但对Token认证来说不是问题因为其保存在请求头中。如果我们将会话转移到客户端也就是说使用Token认证此时将解除会话对服务端的依赖同时也可水平扩展不受浏览器限制但是与此同时也会带来一定的问题一是令牌的传输安全性对于令牌传输安全性我们可使用HTTPS加密通道来解决二是与存储在Cookie中的SessionId相比JWT显然要大很多因为JWT中还包含用户信息所以为了解决这个问题我们尽量确保JWT中只包含必要的信息大多数情况下只包含sub以及其他重要信息对于敏感信息我们也应该省略掉从而防止XSS攻击。JWT的核心在于声明声明在JWT中是JSON数据也就是说我们可以在JWT中嵌入用户信息从而减少数据库负载。所以综上所述JWT解决了其他会话存在的问题或缺点更灵活、更安全、减少数据库往返从而实现水平可伸缩、防篡改客户端声明、移动设备上能更好工作、适用于阻止Cookie的用户综上关于JWT在有效期内没有强制使其无效的能力而完全否定JWT的好处显然站不住脚当然不可辩驳的是若是没有如上诸多使用限制实现其他类型的身份验证完全也是合情合理且合法的需综合权衡而非一家之言下死结论。到目前为止我们一直讨论的是JWT VS Session认证而不是JWT VS Cookie认证但是如标题我们将Cookie也纳入了只是想让学习者别搞混了因为JWT VS Cookie认证这种说法是错误的Cookie只是一种存储和传输信息介质只能说我们可以通过Cookie存储和传输JWT。接下来我们来实现Cookie存储和传输JWT令牌。JWT AS Cookies Identity Claim在Startup中我们可以添加如下Cookie认证中间件此时我们有必要了解下配置Cookie的一些选项通过对这些选项的配置来告知Cookie身份认证中间件在浏览器中的表现形式我们看下几个涉及到安全的选项。配置HttpOnly标志着Cookie是否仅供服务端使用而不能通过前端直接访问。配置SecurePolicy将限制Cookie为HTTPS在生产环境建议配置此参数同时支持HTTPS。配置SameSite用来指示浏览器是否可以将Cookie与跨站点请求一同使用若是对于OAuth身份认证可设置为Lax允许外部链接重定向发出比如POST请求而维持会话若是Cookie认证设置为Restrict因为Cookie认证只适用于单站点若是设置为None则不会设置Cookie Header值。注意SameSite属性在谷歌、火狐浏览器均已实现对于IE11好像不支持Safari从版本12.1开始支持该属性在创建.NET Core默认Web应用程序时在ConfigureServices方法中通过中间件直接配置了全局Cookie策略如下当然默认配置了全局Cookie策略同时也在Configure方法中使用其策略如下我们也可以直接在上述调用使用Cookie策略中间件的方法中来设置对应参数策略如下若是我们在添加Cookie中间件的同时也配置全局Cookie策略我们会发现对于属性HTTPOnly和SameSite都可配置此时个人猜测会存在覆盖的情况如下对于需要认证的控制器我们需要添加上[Authroize]特性对每一个控制器我们都得添加这样一个特性相信大部分童鞋都是这么干的。其实我们大可反向操作对于无需认证的我们添加可匿名访问特性即可而需要认证的控制器我们进行全局配置认证过滤器如下好了到了这里我们只是粗略的讲解了下关于Cookie中间件参数配置和Cookie全局配置策略的说明没有太深入去研究里面的细枝末节等遇到问题再具体分析吧。继续回到话题Cookie认证相比JWT对API访问来讲安全系数低所以我们完全可以在Cookie认证中结合JWT来使用。具体我们可尝试怎么搞呢将其放到身份信息声明中我想应该是可行的方式我们来模拟登陆和登出试试大概代码如下上述代码很简单无需我再多讲和Cookie认证无异只是我们在声明中添加了access_token来提高安全性接下来我们自定义一个Action过滤器特性并将此特性应用于Action方法如下JWT Combine Cookie Authentication如上是采用将JWT放到声明的做法我想这么做也未尝不可至少我没找到这么做有什么不妥当的地方。我们也可以将Cookie认证和JWT认证进行混合使用只不过是在上一节的基础上添加了Cookie中间件罢了如下图通过如上配置后我们就可以将Cookie和JWT认证来组合使用了比如我们在用户登录后如下图点击登录后显示当前登录用户名然后点击退出在退出Action方法上我们添加组合特性在上一节中我们通过获取AccessToken从而访问端口号为5001的客户端来获取当前时间那现在我们针对获取当前时间的方法添加上需要Cookie认证如下Cookie认证撤销在.NET Core 2.1版本通过Cookie进行认证中当用户与应用程序进行交互修改了信息需要在cookie的整个生命周期也就说在注销或cookie过期之前看不到信息的更改时我们可通过cookie的身份认证事件【撤销身份】来实现这样的需求下面我们来看看。我们通过重写CookieAuthenticationEvents事件中的ValidatePrincipal然后判断写在内存中关于用户表示是否存在若存在则调用 context.RejectPrincipal() 撤销用户身份。然后我们在添加Cookie中间件里配置该事件类型以及对其进行注册接下来我们写一个在页面上点击【修改信息】的方法并在内存中设置撤销指定用户如下从如上动图中我们可以看到当点击修改信息后然后将撤销的用户标识写入到内存中然后跳转到Index页面此时调用我们写的撤销事件最终重定向到登录页且此时用户cookie仍未过期所以我们能够在左上角看到用户名不清楚这种场景在什么情况下才会用到。跳转至登录携带或移除参数当我们在某个页面进行操作时若此时Token或Cookie过期了此时则会自动引导用户且将用户当前访问的URL携带并重定向跳转到登录页进行登录比如关于博客园如下跳转URL但是如果我们有这样的业务场景用于跳转至登录页时在URL上需要携带额外的参数我们需要获取此业务参数才能进行对应业务处理那么此时我们应该如何做呢我们依然是重写CookieAuthenticationEvents事件中的RedrectToLogin方法如下这里需要注意的是因为上述我们用到了IActionContextAccessor所以我们需要将其进行对应如下注册最终我们跳转到登录页将会看到我们添加的额外参数id也将呈现在url上如下本节我们讲解了Session和JWT的优缺点以及Cookie认证中可能我们需要用到的地方下一节也是JWT最后一节内容我们讲讲并探讨如何实现刷新Token感谢阅读