网站登录鉴权的实现
什么是网站鉴权,目的是什么?
一般来说,一个网站不可能只有一种操作权限。举个例子,可能存在未登录的操作权限,登录的操作权限,以及管理
员的操作权限等。网站鉴权的目的就是用户在进行操作前,对用户的身份进行识别并判断其是否具有该操作权限的过
程。
网站鉴权的几种方式
这里我们将问题简单化,即操作权限只区分用户是否进行了登录。
Session方式实现
(1)Session实现鉴权
1>用户首先进行登录,如登录成功的话,后台会生成一个唯一的sessionId,并在后台存储对应的用户信息
(redis,数据库等等),并将sessionId写到Cookie。
2>下次该浏览器访问时,会首先判断Cookie,进而确定该用户是否进行了登录操作。
(2)Session一致性问题
即需要将在服务器存储的用户信息放在一块儿(同一个redis,mysql等),否则可能出现在一台机器上登录,
并且在该机器上保存了数据,但下一次请求访问到另一个服务器时,需要重新进行登录的情况。
JWT以及具体实现
(1)JWT鉴权的简单流程
JWT分为三部分:Header(包含加密方式等),Payload(包含用户必要信息,以及过期时间等),
Signature(由前两部分生成)。
1>用户登录成功后,后台根据用户信息加上一个用户唯一的密钥值,生成一串字符串,即Token串,将其设置
在Cookie中;
2>用户下次带Token访问,系统会先根据前两部分以及密钥值,对Token进行有效性以及正确性的验证,如果
验证通过的话,再执行下一步操作...
(2)关于鉴权时机的思考
下面提供两种方式,大家可以根据具体的网站需求进行选择:
1>将接口分为需要进行鉴权的接口(auth),不需要进行鉴权的接口(api),然后通过过滤器对auth接口
进行统一的处理,即登录进行访问,未登录跳回登录页等等逻辑。
2>上面做法存在一个问题,就是当接口中出现无法界定的接口,即登录未登录都可以进行访问。那么,按照上
面的方法就只能对接口进行拆分,分成api和auth接口。
所以,另一种方式就是索性不使用过滤器进行处理,当需要进行登录才能访问,或无法界定的接口的时
候,对token进行验证以及获取,再接着进行下面的逻辑处理。
(3)关于Token刷新的问题
一般Token的有效时间设置为1-2个小时,那么,如果过期之后,就需要重新登录获取Token。为了避免这种
情况,我们可以为Token设置一个刷新有效时间,只要Token在这个刷新有效时间内,使用旧的Token进行访
问,就会给它返回一个新的Token。这样,问题就可以解决。
oauth鉴权,了解一下(应用:第三方登录)
oauth简单来说,就是为了解决一个应用(客户端)中为了获取另一个应用(服务提供商)资源,而不需要用户向
客户端提供服务提供商账号密码信息的这样一个问题。客户端与服务提供商之间,有一个应用授权层,客户端携带
Token通过授权层获取服务提供商的资源。
第三方登录就采用的是oauth2进行授权的,这里有通过Go语言实现QQ和Github第三方登录的代码
总结
我们这里只是简单的探讨了下关于鉴权的几种方式,在实际的开发中,由于安全性,以及网站的复杂性,可能会存
在多种不同的用户权限等等,那么,就可能需要对这些方式进行一定的设计和修改。
原文链接:https://blog.csdn.net/leeezm/article/details/80464847
一、概述
登陆和认证是什么?都是在鉴别用户的身份。如何鉴定识别出这是哪个用户?或者说,有什么方式只有用户自己知道(够安全),又能说出这是他自己?于是就有了"用户名+密码"、"用户名+手机号" 的方式出现。下面主要分析 “用户名+密码”的登陆鉴权方式:
- 出于安全考虑,我们不可能在所有的请求里都使用“用户名+密码”。
- "用户名+密码"不能存储在任何地方,最安全的方式就是存放在用户自己的脑子里,也就是说如果要使用 “用户名+密码” 就得让用户自己提供。
那么我们如何做到可以不用提供用户名和密码呢?我们在用户登录的时候,根据用户的身份信息去生成一种能标记用户的 token。
有了认证信息 token 以后,新的问题就是如何保证这个 token 是安全的呢?如果其他人拿到了这个 token 就能伪造用户身份了。解决方案就是鉴定这个 token 是不是用户本人在使用,一般我们通过以下方式,如果我们能保证下面的两种验证信息是一直都没变或者在可接受的范围内,我们就能认为这个用户一直在使用我们下发的 token。
- 位置信息(ip、经纬度)
- 设备信息
现在我们已经做到了 token + (位置、设备信息)来鉴定用户的身份。如果我们每次请求都要鉴定这些信息来确认用户身份,势必影响我们服务的性能。那么如何减少这样的判定呢?
- 服务端随机或者定时选定一次请求鉴定
- 客户端定时请求一次鉴定
第一种方式不建议,服务器维护每个用户定时复杂,随机可能会有大量用户同时鉴定的性能问题。那么就是第二种了,客户端定时请求一次鉴定,服务端需要强制客户端定时请求一次鉴定,而这个定时时间就是一个安全因素,如果在期间 token 泄露就会造成用户信息安全问题,时间不能太长,也不能太短,参考微信的是 7200s 就是 2 小时。
那么如何强制客户端每隔一段时间做一次验证呢?很简单,我们给 token 设个有效时间,到失效时间客户端就必须请求一次新的 token,于是就有了 refresh token。
二、鉴权方式
用户登录后,每次请求服务时客户端请求都要包含鉴权信息,服务端根据鉴权信息查询用户信息和其合法性。目前鉴权信息可以有如下方式:
1. 集中式 session 方式
在登陆完成后,服务端将返回作为认证鉴权的随机不重复 token,客户端每次请求带上这个 token(一般放在请求的 header 里面)。服务端通过 token 查询到 token 对应的用户信息。
2. 令牌方式
登陆完成后,服务端根据用户信息和其他安全因素加密生成一个安全令牌(也就是 JWTS,JSON Web Tokens),该令牌中包含了用户的身份信息,在认证鉴权时只需验证令牌的合法性即可,解密即可取到用户信息。
3. 比较
鉴权方式 | 优点 | 不足 |
---|---|---|
集中式 session 方式 | 1. 服务端维护用户状态,可以管理用户状态,没有失效和用户信息一致问题;
2. 安全性相对较高 |
1. 服务端维护 Session 状态,根据 Token 获取用户信息需要极高的性能要求 |
令牌方式 | 1. 客户端记录用户状态,服务是无状态的,没有集中式的性能问题。
2. 业务解耦,鉴权逻辑相对简单的多,令牌方式在技术实现性能和可靠性上也相对容易些 |
1. 令牌强制失效或者续签问题,令牌强制失效或更新需要额外工作(比如封禁用户)
2. 当用户信息更新后,令牌里的用户的同步问题 |
三、鉴权实现方案
1. 集中式 session 方式流程时序
- 客户端在未登录的状态下请求业务服务,在网关没有获取到认证信息时直接返回 401,告知客户端需要登录。
- 客户端使用“手机号+密码”、“手机号+验证码”的方式请求登陆服务。
- 网关发现是登陆服务后,请求登陆认证服务。
- 登陆认证服务通过手机号码查询用户信息,同时生成 token。
- 返回网关 token,网关将 token 返回给客户端。
- 客户端带着 token 请求网关,网关将 token 传给鉴权服务,鉴权服务通过 token 查询用户信息并返回给网关,网关将用户信息转给业务服务,完成接下来的业务流程。
2. 令牌方式流程时序
- 客户端在未登录的状态下请求业务服务,在网关没有获取到认证信息时直接返回 401,告知客户端需要登录。
- 客户端使用“手机号+密码”、“手机号+验证码”的方式请求登陆服务。
- 网关发现是登陆服务后,请求登陆认证服务,同时生成 token(JWT信息),并将 token 返回给客户端。
- 客户端带着 token 请求网关,网关根据 token(JWT信息)解密得到用户信息,并将用户信息转给业务服务,完成接下来的业务流程。
四、鉴权技术方案
1. 集中式Session鉴权技术方案
集中式Session鉴权验证用户身份有如下的实现方式:
实现 | 说明 | 优点 | 缺点 |
---|---|---|---|
RPC调用 | 网关通过RPC调用鉴权服务,通过token获取用户信息 | 架构逻辑简单,不需要额外工作 | 增加响应 RT |
Redis 直读 | 网关直接读取鉴权服务的 Redis,验证并获取用户信息 | 高性能 | 需要网关也集成鉴权验证逻辑,并且维护 Redis 的配置 |
Nginx Lua | 在 Nginx 里通过 lua 脚本实现鉴权逻辑 | 性能最好 | 1. 在网关之前,对签名无效的请求也需要做鉴权验证。
2. Nginx 改造,lua 开发成本 |
2. 令牌方式鉴权技术方案
令牌方式鉴权的实现就简单的多, 网关直接解析 JWT 信息获取用户信息,然后带着用户信息去请求业务数据。
本文仅提供参考,是本人闲时所写笔记,如有错误,还请赐教,作者:阿蒙不萌,大家可以随意转载