加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • Session
    • Token
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

现代Web认证与安全管理:深入理解Cookie、Session与Token

5小时前
217
阅读需 11 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

Cookie

Cookie最主要的作用就是用于会话管理,当用户登录一个网站时,服务器会生成一个包含会话ID的Cookie并发送给浏览器,浏览器将这个Cookie保存在本地。此后,每次用户发送请求时,浏览器都会自动将这个Cookie发送给服务器,服务器通过会话ID识别用户身份,从而保持用户的登录状态。Cookie除了用于会话管理,还可以在指客户端持久存储,一般使用kv形式保存。

cookie属性

可以看一下浏览器持久化存储的cookie内容:

Name/value 键值对,cookie的内容。
Domain Domain决定Cookie在哪个域是有效的,也就是决定在向该域发送请求时是否携带此Cookie,Domain的设置是对子域生效的,如Doamin设置为 .a.com,则b.a.com和c.a.com均可使用该Cookie,但如果设置为b.a.com,则c.a.com不可使用该Cookie。Domain参数必须以点(“.”)开始。
Path Cookie的有效路径,和Domain类似,也对子路径生效。
Expires/Max-Age 用于指定Cookie的过期时间。
‌HttpOnly 此属性指定Cookie只能通过HTTP协议访问。
Secure Cookie的安全属性,若设置为true,则浏览器只会在HTTPS和SSL等安全协议中传输此Cookie,不会在HTTP协议中传输此Cookie。
SameSite 该属性用于限制第三方Cookie,防止跨站请求伪造(CSRF)攻击。

浏览器一般会默认限制cookie不支持跨域,如果跨域需要配置合理的CORS策略,即配置白名单。

Session

当客户端第一次访问服务器的时候,此时客户端的请求中不携带任何标识给服务器,此时服务器会新建session标识,当服务器进行响应的时候,服务器会将session标识放到http响应头的Set-Cookie中,以key-value的形式返回给客户端,例:

SESSIONID=xxx;

客户在下次访问服务端的时候,将sessionid带上,服务端根据sessionid从本地内存获取客户会话信息。

由于会有越来越多的用户访问服务器,因此服务端的Session也会越来越多。为防止内存溢出,服务器会把长时间(默认30分钟)没有活跃的Session从内存删除。如果超过了超时时间没访问过服务器,Session就自动失效了,需要重新登录。

分布式session

SESSIONID仅存储在单机服务器会有单点问题,一般解决Session在多个服务器之间的共享问题有几种方法:

1、Sesson Replication

也就是每台Web服务器都保存所有用户的Session数据,网络开销大,性能低。

2、Sesson Sticky

基于Nginx的sticky模块,即让前置负载均衡器根据每次请求的ip/cookie来进行请求的转发,保证一个会话中的每次请求都能落到同一台服务器上面。

缺陷:如果某台服务器宕机,那么它上面存储的Session数据就丢失了,用户就需要重新进行登陆。

负载均衡器变为一个有状态的节点,因为他需要保存Session到具体服务器的映射,和之前无状态的节点相比,内存消耗会更大,容灾方面会更麻烦。

3、Sesson数据集群存储

集中存到外部缓存如Redis中,一般大型系统都会单独部署redis缓存集群。

Session和cookie一样都有可能遭到跨站请求伪造(CSRF)攻击,一般可以使用token解决,对于敏感操作可以双重验证,如用户登陆和资金转账使用独立密码。

Token

Token是身份验证和授权令牌,具有无状态性、跨域支持、安全性等优点,但需注意安全传输、失效管理等问题。Token安全策略包括使用HTTPS、加密存储、设置过期时间等。

常用的jwt token分为三部分:

1、header:指定签名算法和令牌类型。

2、payload:也是一个JSON对象,用于存放需要传递的数据,例如用户的信息uid、权限等,一般还会携带时间戳,用于防止重放攻击。

JWT推荐了payload中的7个可选官方字段:iss (签发人), exp (过期时间),  aud (接收方)等,另外也可以自己协商私有字段。

3、Signature:签名,server根据header获取签名算法,再用公钥根据此签名算法对head+payload 生成签名,这样一个token就生成了。

客户端使用token执行会话流程

1、用户使用用户名和密码进行登录,系统验证用户身份成功后,生成一个Token并返回给客户端。

2、客户端将Token保存在本地,通常是存储在Cookie或LocalStorage中,在每次发送请求时在请求头带上token。

3、服务端验证token,通过后执行业务操作。

4、如果token非法,返回401给客户端,客户端需要执行登录操作。

服务端如何验证token

这里就要考虑token如何生成。Token既可以使用对称加密也可以使用非对称加密(JWT)生成。对称加密中Token 中通常只有 userId 和 timestamp,客户端无法解密token也无法往里面添加内容。非对称加密中客户端可以使用公钥解密token获取用户信息,也可以使用公钥打包添加额外信息。

为了安全起见,防止token被攻击者盗用,token 的有效期不会设置的太长,这样就会由于 token过期导致用户需要重新登录从而生成新的token。服务端验证token过期会返回401,前端重定向到登录页面。如何才能做到不需要用户去频繁的登录呢,有下面两种形式。

1、单token方案

2、双token方案,Refresh Token机制

Oauth2认证规范中把之前的那个Token称为Access Token,业务方用这个 Access Token进行认证鉴权。而Refresh Token是专门用来在Access Token过期后重新获取新的Access Token的Token。

Refresh Token的过期时间一般设置长一点

比如一天,Access Token的过期时间设置短一点比如30分钟,这样可以缩短Access Token的过期时间保证安全,同时又不会因为频繁过期重新要求用户登录。

Access Token每次访问都要携带,因此更容易被盗取;Refresh Token被盗的风险远小于Access Token。

Token失效与管理

Token是由客户端保存的,一旦服务器生成,它就一直有效,直到过期。换句话说,服务器无法主动让一个Token失效,除非将Token放入“黑名单”中,这样每次验证Token时都需要先检查这个黑名单。如果Token在黑名单里,就会被认为无效。但问题是,黑名单必须保存在服务器端,这意味着如果要支持服务器随时“踢掉”用户,就相当于将服务变成了“有状态”的管理,类似于Session模式。

所以,一般情况下,当客户端登出时,最简单的方法是直接删除本地存储的Token,用户下次登录时,服务器会重新生成一个新的Token。

对于大规模用户的系统,通常会部署独立的认证系统,并使用如Redis集群这种方式来存储Session,这样就能更方便地管理Token的过期和刷新问题。

通常,Token是存放在HTTP请求头中的Authorization字段,而不是放在Cookie里。这样做的主要原因是为了解决跨域请求时无法共享Cookie的问题。对于跨域问题,通常需要在服务器端配置允许来自所有域的请求,这可以通过设置Access-Control-Allow-Origin: *来实现。

基于token可以实现SSO单点登录,只需要各个服务器都使用同一个密钥对token进行加密解密即可。

相关推荐

电子产业图谱

机械转行IT狗,目前在阿里巴巴淘宝事业群。日常记录Linux应用开发、嵌入式操作系统、无线网络协议栈。刚深入使用Java,跟大家一起入门交流。