HTTP Basic Authentication

优点:
简单,广泛支持。
缺点:

  1. 用户HTTP是在网络上裸奔的,所以这个基本认证的用户名和密码也是可以被人看到的,虽然它使用了Base64来编码,但这个编码很容易就可以解码出来。
  2. 即使这个认证内容不能被解码为原始的用户名和密码也是不安全的,恶意用户可以在获取了认证内容后使用其不断的向服务器发起请求,这就是所谓的重放攻击。
  3. 像中间人攻击就更不能防止了,中间人可以修改报文然后请求服务器。

适用:
内部网络,或者对安全要求不是很高的网络。现如今HTTP基本认证都是会结合HTTPS一起使用的,https保证网络的安全性,然后基本认证来做客户端身份识别。在结合了HTTPS后,Basic Authentication 可以说还是有一定的市场的,但是其重要性正在降低。因为合适的使用场景太少。我们可以想象一下:如果服务器是允许匿名用户访问的,那你就没有必要认证。如果服务器是不允许匿名访问的,那么需要用户注册,就会使用用户凭证认证,也不需要基本认证。只有那种只需要一个特定密码就可以访问的场景,例如加了提取码的网盘资源。

session-cookie

优点:
其实是从文档式网页到交互式网页过程中为了解决身份认证问题而提出的一种早期方案。
缺点:

  1. session一般是存在内存里的,随着用户的增多,服务器的开销也明显变大了。
  2. 以上问题可以通过适当增加服务器来满足需求,但这样session的认证方式就会出现问题,比如已登录的用户session存在服务器A上,可是由于负载均衡,下次请求到了另一台服务器B上,服务器B没有保存session,则又要求用户再次登录,这明显是不合理的。
  3. Tomcat服务器提供了集群之间session共享的解决方案,不同服务器之间通过复制更新session的方式来共享session,但如果集群的数量很多,检查和复制的行为会占去一定资源,因此这种方式在服务器比较多的情况下是不理想的。
  4. 如果通过哈希的方式某个用户请求路由到某一台服务器上,那么这个用户只需在这台服务器上保存session,可以解决上述问题,但同时这也限制了集群负载均衡的能力,可能会出现某一时刻,大量的请求到达某一台服务器,但是其他服务器又相对空闲的情况。
  5. 最后一点,由于sessionid是基于cookie存储的方式保存,如果cookie被截获,用户就容易受到跨站请求伪造的攻击,这是不安全的。

适用:
早期的web。

Token 验证

优点:

  1. session和cookie机制是在客户端与服务端之间保持一个状态,服务端创建session对象也是需要开辟一定的内存空间来保存登陆状态的,但是利用Token的话就不会保持状态,只需比对令牌是否有效即可。
  2. 也就是说Token是不存储在服务器的,这个Token本身就保存着登陆状态,服务器根据事先定义好的规则进行解密就可以知道该Token是否合理。除此之外,我们知道不只是浏览器是代理客户端,手机APP也是,在手机上面cookie是不起作用的,那么就限制了客户端类型,Token验证就不会有这个问题。

缺点:
当后端在token 有效期内废弃一个 token 或者更改它的权限的话,不会立即生效,一般需要等到有效期过后才可以。另外,当用户 Logout 的话,token 也还有效。除非,我们在后端增加额外的处理逻辑。
适用:
token验证比较灵活,适用于大部分场景。常用的token鉴权方式的解决方案是JWT,JWT是通过对带有相关用户信息的json进行加密,加密的方式比较灵活,可以根据需求具体设计。JWT 最适合的场景是不需要服务端保存用户状态的场景,比如如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。
jwt相关问题:
4.1 用户登出,如何设置token无效?
JWT是无状态的,用户登出设置token无效就已经违背了JWT的设计原则,但是在实际应用场景中,这种功能是需要的,那该如何实现呢?提供几种思路:

  • 用户登出,浏览器端丢弃token
  • 使用redis数据库,用户登出,从redis中删除对应的token,请求访问时,需要从redis库中取出对应的token,若没有,则表明已经登出

4.2 使用redis,两个不同的设备,一个设备登出,另外一个设备如何处理?
请思考这样一种场景:

  • 同一个用户从两个设备登陆到服务端(设备1,设备2);
  • 设备1登出,删除redis中的对应的token - 设备2再次请求数据时,redis中的数据为空,需要重新登录。
    很明显,这种情况是不应该出现的,想法是:
  • 每一个设备与用户生成唯一的key,保存在redis中,即设备1的用户登出,只删除对应的token,设备2的token仍然存在

OAuth2(开放授权)

这种方法用的是最多的,我们常见的一些网站比如CSDN、掘金等都可以利用微信和QQ进行登陆的,无须使用其他的用户名和密码。这种方式就可以省略了很多步骤,使得用户体验良好。
四种模式:

  1. 授权码模式
    第一步:用户访问页面
    第二步:访问的页面将请求重定向到认证服务器
    第三步:认证服务器向用户展示授权页面,等待用户授权
    第四步:用户授权,认证服务器生成一个code和带上client_id发送给应用服务器。然后,应用服务器拿到code,并用client_id去后台查询对应的client_secret
    第五步:将code、client_id、client_secret传给认证服务器换取access_token和refresh_token
    第六步:将access_token和refresh_token传给应用服务器
    第七步:验证token,访问真正的资源页面

优点:安全性、refresh_token用于换取新token、用户信息存在应用服务器暴露风险小
缺点:多次请求
适用:市面主流第三方验证
2. 简化模式
第一步:用户访问页面时,重定向到认证服务器。
第二步:认证服务器给用户一个认证页面,等待用户授权。
第三步:用户授权,认证服务器向应用页面返回Token
第四步:验证Token,访问真正的资源页面

优点:简单
缺点:应用页面没有后台、不能存储获取refresh_token的必要信息、token过期处理、token暴露风险
适用:应用只有页面,没有后台管理,只能使用第三方认证后,直接访问(问卷、评论)
3. 密码模式
第一步:用户访问用页面时,输入第三方认证所需要的信息(QQ/微信账号密码)
第二步:应用页面那种这个信息去认证服务器授权
第三步:认证服务器授权通过,拿到token,访问真正的资源页面

优点:不需要多次请求转发,额外开销,同时可以获取更多的用户信息。(都拿到账号密码了)
缺点:局限性,认证服务器和应用方必须有超高的信赖。(比如亲兄弟?)
适用:自家公司搭建的认证服务器。
4. 客户端模式
第一步:用户访问应用客户端
第二步:通过客户端定义的验证方法,拿到token,无需授权
第三步:访问资源服务器A
第四步:拿到一次token就可以畅通无阻的访问其他的资源页面。

优点:方便,这是一种最简单的模式,只要client请求,我们就将AccessToken发送给它。
缺点:不安全,要求我们对client完全的信任,而client本身也是安全的。
适用:一般用来提供给我们完全信任的服务器端服务。在这个过程中不需要用户的参与。

目前使用的鉴权方法

字节跳动argus平台鉴权机制 Basic Authorization
字节跳动Oort-Gateway OpenAPI 方案 jwt
Codebase 鉴权方案 jwt
百度大脑openapi鉴权机制 OAuth2.0
新浪微博授权机制 OAuth2.0
华为云业务面api认证鉴权 Token认证
腾讯云消息队列TDMQ jwt鉴权 Token认证
腾讯云接口鉴权 Token认证
阿里云dataworks数据服务鉴权方式 签名认证/复杂认证(AppKey&AppSecret)

权限控制

ACL: Access Control List 访问控制列表
以前盛行的一种权限设计,它的核心在于用户直接和权限挂钩
优点:简单易用,开发便捷
缺点:用户和权限直接挂钩,导致在授予时的复杂性,比较分散,不便于管理
例子:常见的文件系统权限设计, 直接给用户加权限
RBAC: Role Based Access Control
基于角色的访问控制系统。权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限
优点:简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来
缺点:开发对比ACL相对复杂
例子:基于RBAC模型的权限验证框架与应用 Apache Shiro、spring Security、casbin
RBAC: with Domains: Role Based Access Control With Domains
相较rbac多了一个租户域
ABAC: Attribute-based Access Control
基于属性的权限验证控制
ABAC则是通过动态将一个或一组属性来判断是否满足设定的条件来进行授权判断。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性)
优点:配置非常灵活,能够满足几乎所有需求
缺点:管理起来非常复杂且不直观
例子:“允许所有班主任在上课时间自由进出校门” 这条规则,其中,“班主任” 是用户的角色属性,“上课时间” 是环境属性,“进出” 是操作属性,而 “校门” 就是对象属性了。
UGO(User, Group, Other)
这个是Linux中对于资源进行权限管理的访问模型。Linux中一切资源都是文件,每个文件都可以设置三种角色的访问权限(文件创建者,文件创建者所在组,其他人)。这种访问模型的缺点很明显,只能为一类用户设置权限,如果这类用户中有特殊的人,那么它无能为力了
DAC(自主访问控制)
在ACL的访问控制模式下,有个问题,能给资源增加访问控制的是谁,这里就有几种办法,比如增加一个super user,这个超级管理员来做统一的操作。还有一种办法,有某个权限的用户来负责给其他用户分配权限。这个就叫做自主访问控制。
MAC(强制访问控制)
强制访问控制和DAC相反,它不将某些权限下放给用户,而是在更高维度(比如操作系统)上将所有的用户设置某些策略,这些策略是需要所有用户强制执行的。这种访问控制也是基于某些安全因素考虑。