Spring Security OAuth认证详解

589 阅读11分钟

SPEL(Spring Expression Language)

SpEL 的基本语法

  • # :用于引用变量或上下文中的对象。例如:#name 表示引用变量 name
  • @ :用于引用 Spring 容器中的 Bean。例如:@myBean 表示引用名为 myBean 的 Spring Bean。
  • . :用于访问对象的属性或方法。例如:#user.name 表示访问 user 对象的 name 属性。
  • 逻辑运算:支持 andor! 等逻辑运算符。
  • 方法调用:可以直接调用对象的方法。例如:#user.hasRole('ADMIN')

PreAuthorize

@PreAuthorize 是 Spring Security 提供的一个注解,用于在方法执行前进行权限检查。它支持 SpEL 表达式,并且可以访问一些内置对象和变量。

常见的内置对象和变量

(1) #oauth2
  • 这是 Spring Security OAuth2 提供的一个内置对象,用于访问 OAuth2 相关的信息。

  • 常用方法:

    • #oauth2.hasScope('scope'):检查当前用户是否具有指定的 OAuth2 作用域。
    • #oauth2.clientId:获取当前客户端的 clientId
    • #oauth2.isUser():检查当前是否是用户身份(而不是客户端身份)。
(2) # + 方法参数
  • 你可以直接使用方法中的参数作为变量。例如:
@PreAuthorize("#name == 'admin'")
public void doSomething(String name) {
    // 只有 name 为 admin 时才能调用此方法
}
(3)principal
  • 表示当前认证的用户主体(Principal 对象)。
  • 通常是一个 UserDetails 对象或 OAuth2 用户信息。
(4)authentication
  • 表示当前的 Authentication 对象,包含用户的认证信息。
(5)hasRolehasAuthority
  • 这是 Spring Security 提供的内置方法,用于检查用户是否具有指定的角色或权限。

OAuth2.0

OAuth 2.0 是一种授权框架,允许第三方应用在用户授权的情况下访问用户的资源。

五种的角色:

1. 资源所有者(Resource Owner)

  • 定义:资源所有者是拥有受保护资源(如用户数据)的实体,通常是最终用户。

2. 客户端(Client)

  • 定义:客户端是请求访问受保护资源的应用程序,可以是 Web 应用、移动应用或后端服务。

3. 授权服务器(Authorization Server)

  • 定义:授权服务器负责验证资源所有者的身份并颁发访问令牌。

4. 资源服务器(Resource Server)

  • 定义:资源服务器是托管受保护资源的服务器。

5. 用户代理(User Agent)

  • 定义:用户代理是资源所有者与客户端、授权服务器交互的工具,通常是浏览器或移动应用。

6. 资源(Resource )

  • 定义:例如用户数据、订单信息、照片等

四种授权模式

1. 授权码模式(Authorization Code)

流程
  1. 客户端将用户重定向到授权服务器的登录页面。
  2. 用户在授权服务器上登录并授权。
  3. 授权服务器返回一个授权码给客户端。
  4. 客户端使用授权码授权服务器请求访问令牌
  5. 授权服务器返回访问令牌,客户端使用该令牌访问资源服务器
特点
  • 安全性高,授权码通过前端传递,访问令牌通过后端交换。
  • 支持刷新令牌(Refresh Token)。
应用场景
  • Web 应用:用户通过浏览器访问的网站,如电商平台、博客系统。

    • 例子:用户登录淘宝时,淘宝(客户端)会跳转到支付宝(授权服务器)进行授权,支付宝返回授权码,淘宝用授权码换取访问令牌。
  • 移动应用:安装在手机上的应用程序,如微信、抖音。

    • 例子:用户登录抖音时,抖音(客户端)会跳转到微信(授权服务器)进行授权,微信返回授权码,抖音用授权码换取访问令牌。

案例:用户登录淘宝并查看订单

角色对应
  • 资源所有者:用户(淘宝的消费者)。
  • 客户端:淘宝(Web 应用)。
  • 资源:用户的订单信息。
  • 资源服务器:订单服务(存储和管理订单数据的后端服务)。
  • 授权服务器:支付宝(负责用户登录和授权)。
  • 用户代理:用户的浏览器。
流程
  1. 用户打开浏览器(用户代理),访问淘宝(客户端)。
  2. 淘宝将用户重定向到支付宝(授权服务器)的登录页面。
  3. 用户在支付宝上登录并授权淘宝访问其订单信息(资源)。
  4. 支付宝 返回一个 授权码 给淘宝(通过浏览器重定向)。
  5. 淘宝使用授权码向支付宝请求访问令牌
  6. 支付宝 验证授权码并返回 访问令牌 给淘宝。
  7. 淘宝使用访问令牌向 订单服务(资源服务器) 请求用户的订单信息。
  8. 订单服务验证访问令牌,确认有效后返回订单数据。
  9. 淘宝将订单信息展示给用户。

2. 隐式模式(Implicit)

流程
  1. 客户端将用户重定向到授权服务器的登录页面。
  2. 用户在授权服务器上登录并授权。
  3. 授权服务器直接将访问令牌返回给客户端(通过 URL 片段)。
特点
  • 适用于无法安全存储客户端凭证的场景
  • 访问令牌直接通过前端传递,安全性较低,不推荐。
  • 不支持刷新令牌。
应用场景
  • 单页应用(SPA) :所有页面内容通过 JavaScript 动态加载的 Web 应用,如 Gmail、Google Docs。

    • 例子:用户登录 Gmail 时,Gmail(客户端)会跳转到 Google 登录页面(授权服务器),Google 直接将访问令牌返回给 Gmail。
  • 移动应用:适用于无法安全存储客户端凭证的场景。

    • 例子:某些移动应用可能使用隐式模式简化流程,但安全性较低,不推荐。

案例:用户登录 Gmail 并查看邮件

角色对应
  • 资源所有者:用户(Gmail 的用户)。
  • 客户端:Gmail(单页应用,SPA)。
  • 资源:用户的邮件数据。
  • 资源服务器:Gmail邮件服务(存储和管理邮件的后端服务)。
  • 授权服务器:Google登录服务(负责用户登录和授权)。
  • 用户代理:用户的浏览器。
流程
  1. 用户打开浏览器(用户代理),访问 Gmail(客户端)。
  2. Gmail将用户重定向到Google 登录页面(授权服务器)。
  3. 用户在Google登录页面上登录并授权Gmail 访问其邮件数据(资源)。
  4. Google直接将访问令牌返回给Gmail(通过 URL 片段)。
  5. Gmail使用访问令牌向Gmail邮件服务(资源服务器) 请求用户的邮件数据。
  6. Gmail邮件服务验证访问令牌,确认有效后返回邮件数据。
  7. Gmail将邮件数据展示给用户。

3. 密码模式(Resource Owner Password Credentials)

流程
  1. 用户直接将用户名和密码提供给客户端
  2. 客户端使用用户名和密码向授权服务器请求访问令牌
  3. 授权服务器返回访问令牌
特点
  • 用户凭证直接传递给客户端,安全性较低。
  • 适用于高度信任的客户端。
应用场景
  • 内部系统:企业内部的应用,如员工管理系统。

    • 例子:员工登录公司内部系统时,系统(客户端)直接使用员工的用户名和密码向授权服务器请求访问令牌。
  • 受信任的客户端:客户端和授权服务器由同一团队开发和管理。

    • 例子:某些企业级应用可能使用密码模式简化流程。

案例:员工登录公司内部系统并查看工资单

角色对应
  • 资源所有者:员工(公司内部系统的用户)。
  • 客户端:公司内部系统(Web 应用)。
  • 资源:员工的工资单数据。
  • 资源服务器:工资单服务(存储和管理工资单数据的后端服务)。
  • 授权服务器:公司内部的认证服务(负责用户登录和授权)。
  • 用户代理:员工的浏览器。
流程
  1. 员工打开浏览器(用户代理),访问公司内部系统(客户端)。
  2. 员工在登录页面上输入用户名和密码
  3. 公司内部系统使用用户名和密码公司内部的认证服务(授权服务器) 请求访问令牌
  4. 认证服务验证用户名和密码,并返回 访问令牌
  5. 公司内部系统使用访问令牌向 工资单服务(资源服务器) 请求员工的工资单数据(资源)。
  6. 工资单服务验证访问令牌,确认有效后返回工资单数据。
  7. 公司内部系统将工资单数据展示给员工。

4. 客户端凭证模式(Client Credentials)

流程
  1. 客户端使用自己的凭证(客户端 ID 和客户端密钥)向授权服务器请求访问令牌
  2. 授权服务器返回访问令牌
特点
  • 不需要用户参与,客户端直接访问资源。
  • 适用于客户端访问自己的资源。
应用场景
  • 后端服务:服务器之间的通信,如微服务架构中的服务调用。

    • 例子:订单服务(客户端)需要访问库存服务(资源服务器),订单服务使用自己的凭证向授权服务器请求访问令牌。
  • 自动化任务:定时任务或批处理任务。

    • 例子:每天凌晨的数据同步任务,任务脚本(客户端)使用自己的凭证向授权服务器请求访问令牌。

案例:订单服务访问库存服务以检查库存

角色对应
  • 资源所有者:无(客户端直接访问资源)。
  • 客户端:订单服务(后端服务)。
  • 资源:库存数据。
  • 资源服务器:库存服务(存储和管理库存数据的后端服务)。
  • 授权服务器:公司内部的认证服务(负责颁发访问令牌)。
  • 用户代理:无(后端服务之间直接通信)。
流程
  1. 订单服务(客户端) 使用自己的客户端 ID 和客户端密钥向 公司内部的认证服务(授权服务器) 请求 访问令牌
  2. 认证服务 验证客户端凭证,并返回 访问令牌
  3. 订单服务 使用访问令牌向 库存服务(资源服务器) 请求库存数据。
  4. 库存服务 验证访问令牌,确认有效后返回库存数据。
  5. 订单服务 根据库存数据决定是否允许用户下单。

总结对比

角色授权码模式隐式模式密码模式客户端凭证模式
资源所有者淘宝用户Gmail 用户公司员工
客户端淘宝(Web 应用)Gmail(SPA)公司内部系统(Web 应用)订单服务(后端服务)
资源订单信息邮件数据工资单数据库存数据
资源服务器订单服务Gmail 邮件服务工资单服务库存服务
授权服务器支付宝Google 登录服务公司内部的认证服务公司内部的认证服务
用户代理浏览器浏览器浏览器

备注

Web 应用:通过浏览器访问的应用程序,页面由服务器渲染并返回给浏览器。淘宝、知乎
移动应用:安装在手机或平板上的应用程序,通过应用商店下载。微信、抖音
单页应用(SPA):所有页面内容通过 JavaScript 动态加载,用户操作无需刷新页面。Gmail、腾讯文档
后端服务:运行在服务器上的应用程序,通常为其他应用提供 API 接口。订单服务、库存服务
URL片段:URL片段是URL中#后面的部分,如https://example.com/page#section1

Spring Security OAuth关键类

(1)授权服务器相关

  • AuthorizationServerConfigurerAdapter

    • 用于配置授权服务器的核心行为,如客户端详情、令牌存储、授权端点等。
    • 需要重写 configure 方法来定义配置。
  • ClientDetailsServiceConfigurer

    • 用于配置客户端详情(如 clientIdclientSecret、授权类型等)。
    • 通常通过内存或数据库存储客户端信息。
  • AuthorizationServerEndpointsConfigurer

    • 用于配置授权服务器的端点(如 /oauth/token/oauth/authorize)。
    • 可以指定令牌存储方式、用户详情服务等。
  • TokenStore

    • 用于存储令牌(如访问令牌、刷新令牌)。

    • 常见的实现类:

      • InMemoryTokenStore:将令牌存储在内存中。
      • JdbcTokenStore:将令牌存储在数据库中。
      • JwtTokenStore:用于 JWT 令牌。
  • AuthorizationServerSecurityConfigurer

    • 用于配置授权服务器的安全规则(如 /oauth/token_key 端点的访问权限)。

(2)资源服务器相关

  • ResourceServerConfigurerAdapter

    • 用于配置资源服务器的行为,如资源保护规则、令牌解析方式等。
  • ResourceServerSecurityConfigurer

    • 用于配置资源服务器的安全规则(如令牌验证、资源 ID 等)。
  • DefaultTokenServices

    • 默认的令牌服务实现,用于管理令牌的创建、存储和验证。

(3)OAuth 2.0 令牌相关

  • OAuth2AccessToken

    • 表示 OAuth 2.0 的访问令牌。
  • OAuth2RefreshToken

    • 表示 OAuth 2.0 的刷新令牌。
  • JwtAccessTokenConverter

    • 用于将 JWT(JSON Web Token)与 OAuth 2.0 令牌进行转换。

(4)用户认证相关

  • UserDetailsService

    • 用于加载用户详情(如用户名、密码、权限等)。
    • 通常与 Spring Security 的认证机制结合使用。
  • AuthenticationManager

    • 用于处理用户认证。