一、概述

 登陆和认证是什么?都是在鉴别用户的身份。如何鉴定识别出这是哪个用户?或者说,有什么方式只有用户自己知道(够安全),又能说出这是他自己?于是就有了"用户名+密码"、"用户名+手机号" 的方式出现。下面主要分析 “用户名+密码”的登陆鉴权方式:

  1. 出于安全考虑,我们不可能在所有的请求里都使用“用户名+密码”。
  2. "用户名+密码"不能存储在任何地方,最安全的方式就是存放在用户自己的脑子里,也就是说如果要使用 “用户名+密码” 就得让用户自己提供。

 那么我们如何做到可以不用提供用户名和密码呢?我们在用户登录的时候,根据用户的身份信息去生成一种能标记用户的 token。

 有了认证信息 token 以后,新的问题就是如何保证这个 token 是安全的呢?如果其他人拿到了这个 token 就能伪造用户身份了。解决方案就是鉴定这个 token 是不是用户本人在使用,一般我们通过以下方式,如果我们能保证下面的两种验证信息是一直都没变或者在可接受的范围内,我们就能认为这个用户一直在使用我们下发的 token。

  1. 位置信息(ip、经纬度)
  2. 设备信息

 现在我们已经做到了 token + (位置、设备信息)来鉴定用户的身份。如果我们每次请求都要鉴定这些信息来确认用户身份,势必影响我们服务的性能。那么如何减少这样的判定呢?

  1. 服务端随机或者定时选定一次请求鉴定
  2. 客户端定时请求一次鉴定

第一种方式不建议,服务器维护每个用户定时复杂,随机可能会有大量用户同时鉴定的性能问题。那么就是第二种了,客户端定时请求一次鉴定,服务端需要强制客户端定时请求一次鉴定,而这个定时时间就是一个安全因素,如果在期间 token 泄露就会造成用户信息安全问题,时间不能太长,也不能太短,参考微信的是 7200s 就是 2 小时。

 那么如何强制客户端每隔一段时间做一次验证呢?很简单,我们给 token 设个有效时间,到失效时间客户端就必须请求一次新的 token,于是就有了 refresh token。

二、鉴权方式

 用户登录后,每次请求服务时客户端请求都要包含鉴权信息,服务端根据鉴权信息查询用户信息和其合法性。目前鉴权信息可以有如下方式:

1. 集中式 session 方式

 在登陆完成后,服务端将返回作为认证鉴权的随机不重复 token,客户端每次请求带上这个 token(一般放在请求的 header 里面)。服务端通过 token 查询到 token 对应的用户信息。

2. 令牌方式

 登陆完成后,服务端根据用户信息和其他安全因素加密生成一个安全令牌(也就是 JWTS,JSON Web Tokens),该令牌中包含了用户的身份信息,在认证鉴权时只需验证令牌的合法性即可,解密即可取到用户信息。

3. 比较

三、鉴权实现方案

1. 集中式 session 方式流程时序

登陆鉴权方案设计-LMLPHP

  1. 客户端在未登录的状态下请求业务服务,在网关没有获取到认证信息时直接返回 401,告知客户端需要登录。
  2. 客户端使用“手机号+密码”、“手机号+验证码”的方式请求登陆服务。
  3. 网关发现是登陆服务后,请求登陆认证服务。
  4. 登陆认证服务通过手机号码查询用户信息,同时生成 token。
  5. 返回网关 token,网关将 token 返回给客户端。
  6. 客户端带着 token 请求网关,网关将 token 传给鉴权服务,鉴权服务通过 token 查询用户信息并返回给网关,网关将用户信息转给业务服务,完成接下来的业务流程。

2. 令牌方式流程时序

登陆鉴权方案设计-LMLPHP

  1. 客户端在未登录的状态下请求业务服务,在网关没有获取到认证信息时直接返回 401,告知客户端需要登录。
  2. 客户端使用“手机号+密码”、“手机号+验证码”的方式请求登陆服务。
  3. 网关发现是登陆服务后,请求登陆认证服务,同时生成 token(JWT信息),并将 token 返回给客户端。
  4. 客户端带着 token 请求网关,网关根据 token(JWT信息)解密得到用户信息,并将用户信息转给业务服务,完成接下来的业务流程。

四、鉴权技术方案

1. 集中式Session鉴权技术方案

集中式Session鉴权验证用户身份有如下的实现方式:

2. 令牌方式鉴权技术方案

令牌方式鉴权的实现就简单的多, 网关直接解析 JWT 信息获取用户信息,然后带着用户信息去请求业务数据。

06-06 12:18