Skip to content

Spring Security OAuth2 - 9 入门案例与流程详解

本文主要介绍如何在Spring Security中使用OAuth 2.0进行登录,是Spring Security系列第九篇文章,前八篇文章如下:

1. OAuth 2介绍

关于OAuth 2.0的介绍,详情请参照标准:https://datatracker.ietf.org/doc/html/rfc6749

OAuth 2.0是一个开放的权限框架,使得第三方应用程序在得到资源所有者的授权后,可以访问资源服务器上的资源。

什么意思呢?比如我在GitHub上有一个账号,其中包括昵称、头像等信息,在我授权后,第三方网站比如力扣可以访问我在GitHub网站上的信息。

所以OAuth 2.0框架中包括四个角色:

  • 资源所有者(Resource Owner):表示信息的所有人,比如自然人或组织;
  • 客户端(Client):需要获取资源的第三方,比如力扣;
  • 资源服务器(Resource Sever):表示存放资源的服务器,比如GitHub;
  • 授权服务器(Authorization Sever):授权服务器向资源所有者询问是否授权第三方获取资源,如果资源所有者同意授权,那么客户端可以从资源服务器上获取资源。授权服务器由资源服务器所在组织提供,比如GitHub;

在OAuth 2.0中,授权类型有四种:

  • Authorization Code(授权码模式):在资源所有者同意授权后,授权服务器向客户端(前端界面)返回一个授权码,然后跳转到回调地址,客户端(前端界面)将授权码发送给客户端(后台服务),后台服务获取到授权码后再请求授权服务器获取访问令牌,再通过访问令牌获取资源;
  • Implicit(隐式模式):在资源所有者同意授权后,授权服务器直接返回访问令牌,然后客户端通过访问令牌获取资源;
  • Resource Owner Password Credentials(密码模式):用户在客户端输入账号和密码,客户端使用账号密码向授权服务器获取访问令牌,再通过访问令牌获取资源;
  • Client Credentials(客户端凭据模式):客户端使用其自身的凭据(客户端 ID 和客户端密钥)向授权服务器请求访问令牌,客户端通过访问令牌获取资源;

2. GitHub设置

在开始OAuth 登录之前,我们需要在OAuth提供者处创建一个OAuth应用,此处以GitHub为例:

首先新建一个OAuth应用:

image-20250119203338341

在OAuth应用设置界面,填写相关信息:

注意:回调地址的路径,一定要填写/login/oauth2/code/github(这是Spring Security OAuth中写死的)

image-20250119203648974

点击注册应用后,我们就可以得到client id ,点击生成client secret,得到client secret:

image-20250119203945448

自此,我们的GitHub设置就完成了!

3. 入门案例

首先新建一个Spring Boot项目,然后引入依赖:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

然后在配置文件application.properties中配置OAuth信息:

properties
spring.application.name=oauth-demo
server.port=8080

logging.level.org.springframework.security=trace

spring.security.oauth2.client.registration.github.client-id=xxxxx(填写github设置界面的client id)
spring.security.oauth2.client.registration.github.client-secret=xxxxx(填写github设置界面的client secret)

然后在配置类中启用OAuth 登录:

java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .oauth2Login(Customizer.withDefaults())
                .formLogin(Customizer.withDefaults())
                .authorizeHttpRequests(x-> x.anyRequest().authenticated());

        return http.build();
    }
}

编写Controller:

java
@RestController
public class MainController {

    @GetMapping("/resource")
    public String home() {
        return "Hello, OAuth!";
    }
}

启动项目,访问http://127.0.0.1:8080/resource,页面会重定向到登录界面:

image-20250119205242408

可以看到,在账号密码登录下又多了GitHub登录方式。点击GitHub登录链接,跳转到授权服务器提供的授权请求界面:

image-20250119205451189

当我们点击授权后,经过页面跳转后,会返回最初的/resrouce内容:

image-20250119205542843

4. 流程详解

这里就不用文字描述整个流程了,图中已经按序号文字标注了。

spring-boot-starter-oauth2-client依赖中主要有两个过滤器用于OAuth登录:

  • OAuth2AuthorizationRequestRedirectFilter:当用户在登录界面点击使用GitHub登录时,用于重定向到GitHub授权服务器提供的授权界面;
  • OAuth2LoginAuthenticationFilter:当用户同意授权后,授权服务器会使浏览器跳转到回调地址(http://127.0.0.1:8080/login/oauth2/code/github),并且携带code和state,这个拦截器拦截该路径,获取code和state,请求授权服务器获取访问令牌,然后再使用访问令牌去资源服务器获取个人信息,完成登录。