您的当前位置:首页正文

Spring security + Oauth2 + Jwt认证鉴权方案

2024-11-29 来源:个人技术集锦

基础概念

  • 用户身份认证

    用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问。常见的用户身份认证表现形式有:用户名密码登录,指纹打卡等方式

  • 用户授权

    用户认证通过后去访问系统的资源,系统会判断用户是否拥有访问资源的权限,只允许访问有权限的系统资源,没有权限的资源将无法访问

  • 五种认证机制

  • 用户身份认证

    用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问。常见的用户身份认证表现形式有:用户名密码登录,指纹打卡等方式

  • 301表示资源不在旧位置,永久移动到新位置。新位置的URL信息在response中的Location中;302同301类似,区别在于目标资源只是临时移动到新位置;

    浏览器在获取到302的响应值后,会拿到响应头中的Location中的URL,并跳转到该URL

业务场景

  • 登录
    用户登录系统,请求各种资源。

  • 单点登录(Single Sign On)
    简称为 SSO,用于企业业务整合的解决方案之一,是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统

  • 第三方认证

    当需要访问第三方系统的资源时需要首先通过第三方系统的认证(例如:微信认证),由第三方系统对s用户认证通过,并授权资源的访问权限(一般访问用户信息)。

OAuth2

OAuth2 认证的好处就是你只需要一个账号密码,就能在各个网站进行访问,而面去了在每个网站都进行注册的繁琐过程,如:很多网站都可以使用微信登录,网站作为第三方服务、微信作为服务提供商。

OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发token(令牌),使得第三方应用可以使用该令牌在限定时间限定范围访问指定资源。

假设张三使用微信登录微博的场景 ,

  • 张三是一个微信用户,那么微信资源服务器(此处是存储用户信息的服务器)中就保存了张三的用户信息(张三在注册微信时录入的内容),此时微信资源服务器中张三的用户信息就是一种资源,且该资源的拥有者是张三。
  • 有一天,张三第一次访问微博(微博是第三方应用,且微博这个应用已经在微信授权服务器(不是资源服务器)中获得了一个唯一标识),微博要求张三注册账号并输入用户信息。
  • 由于这些用户信息同微信服务器中的用户信息十分类似,微博提供使用微信账号登录的方式来登录微博,用户只需做一下授权就可以直接登录微博,不用再输入用户信息。
  • 用户信息由微博后台从微信资源服务器中获取,这个获取用户信息的过程就是Oauth2的工作过程。

上面过程的最后一步的概要目标是,微博后台想要拿到微信服务器中张三的用户信息,首先需要获得张三的授权(一般是弹出页面点击同意即可),然后微信授权服务器会给微博后台发放一个access_token,微博后台拿着这个access_token就可以去访问微信资源服务器中的张三用户信息。

特别强调的是,此处的授权指的是 在用户的参与下,一个授权服务器(管理一堆资源服务)给另一个应用(第三方应用)颁发一个访问令牌,颗粒度比较大,是应用或服务级的授权。

四种客户端授权方式

OAuth2一般多采用授权码方式,完成两个服务之间的授权。此处

  • 授权码模式(authorization code) 参考资料
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

spring security

spring security是一个安全管理框架,主要核心功能

  • 认证(Authentication):指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。
  • 授权(Authorization):指的是验证某个用户是否有权限执行某个操作

其核心就是一组过滤器链,添加依赖之后,项目启动后将会自动配置。最核心的就是 Basic Authentication Filter 用来认证用户的身份,一个在spring security中一种过滤器处理一种认证方式。

spring security和shiro都是安全管理框架,后者使用简单功能稍弱,一般和ssm配合构建项目。 spring security功能强大,但是操作复杂,一般配合springboot/cloud(自动化配置)一起使用。

特别强调的是,spring security侧重用户和系统之间的请求管理,即某一个用户是否可以访问系统,可以访问系统哪些资源。

JWT

有了 OAuth2和spring security 就可以一个安全管理框架,其操作流程如下

  1. 用户首次访问资源服务器时,资源服务器会将该请求转发到授权服务器
  2. 授权服务器会拦截请求并返回用户一个token ,同时授权服务器将该token和用户的对应信息存储在授权服务器的session中
  3. 浏览器将token存储在本地的cookie中,下一次访问资源服务器携带该token
  4. 此时用户虽然是非首次访问,但仍旧需要先在授权服务器上认证授权,然后才能去访问资源服务器。

问题出来第4步,普通的oauth2颁发的就是一串随机hash字符串,本身无意义。OAuth2的token技术最大的问题是不携带用户信息,且资源服务器无法进行本地验证,每次对于资源的访问,资源服务器都需要向认证服务器发起请求,一是验证token的有效性,二是获取token对应的用户信息。如果有大量的此类请求,无疑处理效率是很低的,且认证服务器会变成一个中心节点,对于SLA和处理性能等均有很高的要求,这在分布式架构下是很要命的。

JWT就是在这样的背景下诞生的,从本质上来说,jwt就是一种特殊格式的token。而jwt格式的token是有特定含义的,它包含了yoghurt信息,分为三部分:

  • 头部Header
  • 载荷Payload
  • 签名Signature

这三部分均用base64进行编码,当中用.进行分隔,一个典型的jwt格式的token类似xxxxx.yyyyy.zzzzz

认证服务器通过对称或非对称的加密方式利用payload生成signature,并在header中申明签名方式,仅此而已。通过这种本质上极其传统的方式,jwt可以实现分布式的token验证功能,即资源服务器通过事先维护好的对称或者非对称密钥(非对称的话就是认证服务器提供的公钥),直接在本地验证token,这种去中心化的验证机制无疑很对现在分布式架构的胃口。jwt相对于传统的token来说,解决以下两个痛点:

  • 通过验证签名,token的验证可以直接在本地完成,不需要连接认证服务器
  • 在payload中可以定义用户相关信息,这样就轻松实现了token和用户信息的绑定

在上面的那个资源服务器和认证服务器分离的例子中,如果认证服务器颁发的是jwt格式的token,那么资源服务器就可以直接自己验证token的有效性并绑定用户,这无疑大大提升了处理效率且减少了单点隐患。

Oauth2 和 spring security 和 Jwt

  • Oauth2是一个标准,即是一个理论,独立无法完成认证和鉴权
  • spring security 是一个框架,它实现了Oauth2,可以基于普通token(随机hash字符串,本身无意义)实现认证和鉴权。
  • jwt是可以包含用户信息的token,Spring security + Oauth2 + Jwt认证鉴权方案可以解决分布式环境下 Spring security + Oauth2方案导致的认证服务器请求多的问题,实现了分布式权限认证。

参考资料

显示全文