之前的一篇文章,发出来跟大家交流一下,有误导的部分还请评论在下面,大家互相进步
还记得在上家公司做全干工程师的时候,基本从页面写到运维,当时做登录这块的时候,被 session、cookie、token 各种概念差点整蒙圈了,上网查询相关概念,发现很多人都是类似的疑惑,比如:
来了新公司之后,前端很少接触 HTTP 请求之后的事情,而且登录相关的 SDK 封装的很好,所以这篇文章就简单的学习记录一下。
首先这是因为HTTP是无状态的协议,所谓无状态就是在两次请求之间服务器并不会保存任何的数据,相当于你和一个人说一句话之后他就把你忘掉了。所以,登录就是用某种方法让服务器在多次请求之间能够识别出你,而不是每次发请求都得带上用户名密码这样的识别身份的信息。 从登录成功到登出的这个过程,服务器一直维护了一个可以识别出用户信息的数据结构,广义上来说,这个过程就叫做 session,也就是保持了一个会话。
忽然想到一点,看了网上很多问题,我觉得大家应该区分两个概念:广义的 session和狭义的 session
**广义的 session:**广义的 session 就是从登录成功到登出的过程,在这个过程中客户端和服务器端维持了保持登录的状态,至于具体怎么维持住这种登录的状态,没有要求。
**狭义的 session:**狭义的 session 就是登录成功后,服务器端存储了一些必须的用户信息,这部分存在服务器端的用户信息就叫做 session,也就是接下来要说的第一种登录的实现方式。
先用图来看:
详细说的说一下,这里面主要是这么几个过程:
客户端带着用户名和密码去访问 /login 接口,服务器端收到后校验用户名和密码,校验正确就会在服务器端存储一个 sessionId 和 session 的映射关系
服务器端返回 response,并且将 sessionId 以 set-cookie 的方式种在客户端,这样一来,sessionId 就存在了客户端。这里要注意的是,将 sessionId 存在 cookie 并不是一种强制的方案,而是大家一般都这么做,而且发请求的时候符合 domain 和 path 的时候,会自动带上 cookie,省去了手动塞的过程。
客户端发起非登录请求时,服务端通过 cookie 中的 sessionId 找到对应的 session 来知道此次请求是谁发出的。
前面说到 sessionId 的方式本质是把用户状态信息维护在 server 端,token 的方式就是把用户的状态信息加密成一串 token 传给前端,然后每次发请求时把 token 带上,传回给服务器端;服务器端收到请求之后,解析 token 并且验证相关信息;
所以跟第一种登录方式最本质的区别是:通过解析 token 的计算时间换取了 session 的存储空间
业界通用的加密方式是 jwt (json web token),jwt 的具体格式如图:
简单的介绍一下 jwt,它主要由 3 部分组成:
header 头部 { "alg": "HS256", "typ": "JWT" } payload 负载 { "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1555341649998 } signature 签名
header 里面描述加密算法和 token 的类型,类型一般都是 JWT ;
payload 里面放的是用户的信息,也就是第一种登录方式中需要维护在服务器端 session 中的信息;
signature 是对前两部分的签名,也可以理解为加密;实现需要一个密钥( secret ),这个 secret 只有服务器才知道,然后使用 header 里面的算法按照如下方法来加密:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
总之,最后的 jwt = base64url(header) + "." + base64url(payload) + "." + signature
jwt 可以放在 response 中返回,也可以放在 cookie 中返回,这都是具体的返回方式,并不重要。
客户端发起请求时,官方推荐放在 HTTP header 中:
Authorization: Bearer <token></token>
这样子确实也可以解决 cookie 跨域的问题,不过具体放在哪儿还是根据业务场景来定,并没有一定之规。
session 方式由于会在服务器端维护 session 信息,单机还好说,如果是多机的话,服务器之间需要同步 session 信息,服务横向扩展不方便。
session 数量随着登录用户的增多而增多,存储会增加很多。
session+cookie 里面存 sessionId 的方式可能会有 csrf 攻击的问题,常见的方式是使用csrf_token来解决
理清概念,一身轻松
--------------------------------------------
鉴于有人说我太明显,我就不放二维码了 欢迎关注我的公众号:fe-yagushou
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.