本博客持续修改与更新中,点击这里查看最新的内容

做了开发几年,登录这块的东西一直了解不多,因为实现的方式有挺多的,我现在要系统的学习一下, 了解一下他们的原理。 目前看了几篇博客,这篇为收集用,之后会用 node 或 java 尝试的写一下。

我上家公司用的这种方式

流程

认证过程大致如下:

  1. 用户输入用户名、密码或者用短信验证码方式登录系统;

  2. 服务端验证后,创建一个 Session 信息,并且将 SessionID 存到 cookie,发送回浏览器;

  3. 下次客户端再发起请求,自动带上 cookie 信息,服务端通过 cookie 获取 Session 信息进行校验;
    弊端

  4. 只能在 web 场景下使用,如果是 APP 中,不能使用 cookie 的情况下就不能用了(app 里用 http 协议);

  5. 即使能在 web 场景下使用,也要考虑跨域问题,因为 cookie 不能跨域(跨域方案, nginx/CORS);

  6. cookie 存在 CSRF(跨站请求伪造)的风险(http-only|https 的下 cookie 设置 secure);

  7. 如果是分布式服务,需要考虑 Session 同步问题(redis);

由于传统的 Cookie-Session 认证存在诸多问题,可以把上面的方案改造一下。改动的地方如下:

  • 不用 cookie 做客户端存储,改用其他方式,web 下使用 local storage,APP 中使用客户端数据库,这样就实现了跨域,并且避免了 CSRF ;
  • 服务端也不存 Session 了,把 Session 信息拿出来存到 Redis 等内存数据库中,这样即提高了速度,又避免了 Session 同步问题;

经过改造之后变成了如下的认证过程:

  1. 用户输入用户名、密码或者用短信验证码方式登录系统;
  2. 服务端经过验证,将认证信息构造好的数据结构存储到 Redis 中,并将 key 值返回给客户端;
  3. 客户端拿到返回的 key,存储到 local storage 或本地数据库;
  4. 下次客户端再次请求,把 key 值附加到 header 或者 请求体中;
  5. 服务端根据获取的 key,到 Redis 中获取认证信息;

JWT

上面的方案虽然经过了改版,但还是需要客户端和服务器端维持一个状态信息,比如用 cookie 换 session ,或者用 key 换 Redis 的 value 信息,基于 JWT 的 Token 认证方案可以省去这个过程。

认证过程

  1. 依然是用户登录系统;
  2. 服务端验证,将认证信息通过指定的算法(例如 HS256)进行加密,例如对用户名和用户所属角色进行加密,加密私钥是保存在服务器端的,将加密后的结果发送给客户端,加密的字符串格式为三个”.” 分隔的字符串 Token,分别对应头部载荷签名,头部和载荷都可以通过 base64 解码出来,签名部分不可以;
  3. 客户端拿到返回的 Token,存储到 local storage 或本地数据库;
  4. 下次客户端再次发起请求,将 Token 附加到 header 中;
  5. 服务端获取 header 中的 Token ,通过相同的算法对 Token 中的用户名和所属角色进行相同的加密验证,如果验证结果相同,则说明这个请求是正常的,没有被篡改。这个过程可以完全不涉及到查询 Redis 或其他存储;

优点

  • 使用 json 作为数据传输,有广泛的通用型,并且体积小,便于传输;
  • 不需要在服务器端保存相关信息;
  • jwt 载荷部分可以存储业务相关的信息(非敏感的),例如用户信息、角色等;

TODO: 实现

##

Auth2

wiki:

TODO: 添加 wiki

第三方认证,Auth 也分好多种, 我看了阮老师的文章,主要下面几种

强制退登,只允许一个用户登录 SSO

参考文章

感谢网上的大佬的指导了