一、OAuth2.0 到底是什么?

1.1 官方定义

OAuth2.0 是开放授权协议,是一个行业标准的授权方案,核心目的是“安全授权、不暴露密码”。

作用:让第三方应用在不获取用户密码的情况下,安全地授权访问用户资源

1.2 大白话理解(一看就懂)

你用 微信登录抖音 时,有没有发现:抖音从来不会让你输入微信密码?

流程很简单:点击微信登录 → 跳转到微信授权页 → 你点击“同意” → 直接登录抖音。

这就是 OAuth2.0 的核心逻辑!它相当于一个“安全中介”,让抖音和微信之间建立授权关系,却不泄露你的微信密码。

✅ 核心优势:

  • 不暴露密码,安全性更高

  • 权限可控,可随时取消授权(比如在微信里取消抖音的授权)

  • 无状态,适合分布式、微服务架构

  • 行业标准,所有大厂都在用(微信、支付宝、GitHub 等)

二、OAuth2.0 四大核心角色

OAuth2.0 有四个固定角色,缺一不可,记住这四个角色,就能轻松理解所有授权流程:

1. Resource Owner(资源所有者)

就是 用户本人(比如你用微信登录抖音,你就是资源所有者),拥有可被访问的资源(头像、昵称、手机号等)。

2. Client(客户端)

就是 第三方应用(比如抖音、小红书、各种网站),需要获取用户的资源来完成功能(比如抖音获取你的微信头像用于登录)。

3. Authorization Server(授权服务器)

负责 登录、校验、颁发 Token 的认证中心(比如微信的认证服务器),核心作用是验证用户身份,给客户端颁发访问凭证(Token)。

4. Resource Server(资源服务器)

存放用户数据、提供业务接口的服务(比如微信的用户信息服务器、你自己项目的接口服务),只有拿到合法 Token,才能访问它的资源。

三、OAuth2.0 四种授权模式(重点掌握2种)

OAuth2.0 定义了 4 种获取 Token 的方式(授权模式),不同场景用不同模式,企业开发中只需要重点掌握2种,其余2种几乎不用。

3.1 授权码模式(最安全、最标准,首选!)

这是最常用、最安全的模式,也是第三方登录(微信、QQ、GitHub)的核心模式,流程稍微复杂,但安全性最高。

完整流程:

  1. 客户端(抖音)跳转至授权服务器(微信)的授权页面;

  2. 用户(你)在授权页面点击“同意”,授权客户端访问自己的资源;

  3. 授权服务器返回一个 code(授权码) 给客户端;

  4. 客户端拿着 code,向授权服务器换取 access_token(访问令牌)

  5. 客户端拿着 access_token,向资源服务器请求用户资源(比如微信头像)。

适用场景:第三方登录、开放平台(比如支付宝开放接口)、面向外部用户的系统。

3.2 密码模式(内部系统专用)

流程最简单,直接用用户的账号密码换取 Token,不需要跳转授权页面。

完整流程:

  1. 用户在客户端(公司内部系统)输入账号密码;

  2. 客户端拿着账号密码,向授权服务器请求 Token;

  3. 授权服务器验证账号密码,验证通过后,直接返回 access_token。

适用场景:公司内部系统(比如OA、CRM)、统一登录平台,只有内部人员使用,安全性可控。

3.3 简化模式(不推荐)

跳过授权码环节,直接返回 access_token,安全性低,适合纯前端应用(无后端),现在几乎不用。

3.4 客户端模式(服务间调用)

不需要用户参与,客户端(服务)直接向授权服务器请求 Token,用于服务之间的调用(比如微服务之间的接口调用)。

四、OAuth2.0 核心令牌(3个关键)

不管哪种授权模式,最终都是为了获取 Token,OAuth2.0 有3个核心令牌,必须分清:

1. access_token(访问令牌)

核心凭证,用于访问资源服务器的接口,短时效(一般1~2小时),过期后需要重新获取。

作用:证明客户端已经获得用户授权,可以访问用户资源。

2. refresh_token(刷新令牌)

用于刷新 access_token 的凭证,长时效(一般7~30天),access_token 过期后,不需要重新登录,用 refresh_token 就能换取新的 access_token。

作用:提升用户体验,避免频繁登录。

3. scope(授权范围)

规定客户端能访问的资源范围,比如“只允许访问用户头像和昵称”“允许访问用户手机号”,避免客户端过度获取用户资源。

五、OAuth2.0 与 JWT 关系

很多人混淆这两个概念,甚至认为它们是“二选一”,其实它们是互补关系,不是替代关系!

用一句话区分:

  • OAuth2.0:是 授权协议/规范,规定了“怎么认证、怎么授权、怎么获取 Token”的流程;

  • JWT:是 令牌格式,规定了 Token 应该怎么存储数据、怎么加密、怎么解析;

  • Spring Security:是 安全框架,负责实现 OAuth2.0 协议、生成 JWT Token、控制接口权限。

举个例子:OAuth2.0 相当于“快递流程规范”,JWT 相当于“快递包裹”,Spring Security 相当于“快递员”,三者结合,才能完成“安全授权”这个“快递任务”。

✅ 企业标准组合:Spring Security + OAuth2.0 + JWT,既能实现安全授权,又能适配分布式架构。

六、SpringBoot 整合 OAuth2.0 + JWT 实战

6.1 项目环境(提前准备)

  • SpringBoot 3.x(兼容 2.7.x)

  • JDK 11+

  • Maven 3.6+

  • Postman(用于测试接口)

6.2 引入核心依赖(pom.xml)

直接复制到 pom.xml 中,无需手动修改:

<dependencies>
    <!-- Web 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Security 安全框架 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- OAuth2 资源服务 + JWT -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <!-- JWT 编解码依赖 -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-jose</artifactId>
    </dependency>
    <!-- Lombok 简化代码(可选) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

6.3 配置文件(application.yml)

简化配置,测试用账号密码(后续可替换为数据库用户):

server:
  port: 8080 # 项目端口

spring:
  security:
    user:
      name: admin # 测试用户名
      password: 123456 # 测试密码
      roles: ADMIN # 测试角色(管理员)

6.4 JWT 配置(RSA非对称加密,安全!)

配置 JWT 的密钥、编码器、解码器,用 RSA 非对称加密(比对称加密更安全),直接复制:

import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;

@Configuration
public class JwtConfig {

    // 1. 生成 RSA 密钥对(非对称加密)
    @Bean
    public KeyPair keyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048); // 密钥长度 2048 位,足够安全
        return generator.generateKeyPair();
    }

    // 2. 配置 JWK(JSON Web Key),用于 JWT 编解码
    @Bean
    public JWKSource<SecurityContext> jwkSource(KeyPair keyPair) {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        RSAKey rsaKey = new RSAKey.Builder(publicKey)
                .privateKey(privateKey)
                .keyID(UUID.randomUUID().toString()) // 唯一密钥ID
                .build();

        JWKSet jwkSet = new JWKSet(rsaKey);
        return new ImmutableJWKSet<>(jwkSet);
    }

    // 3. JWT 编码器(生成 Token)
    @Bean
    public JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
        return new NimbusJwtEncoder(jwkSource);
    }

    // 4. JWT 解码器(解析 Token)
    @Bean
    public JwtDecoder jwtDecoder(KeyPair keyPair) {
        return NimbusJwtDecoder.withPublicKey((RSAPublicKey) keyPair.getPublic()).build();
    }
}

6.5 Security + OAuth2 核心配置(认证+授权关键)

开启 OAuth2 资源服务,配置接口权限、无状态认证,直接复制:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // 开启 Spring Security
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable() // 关闭 CSRF,前后端分离项目必关
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态认证(不创建 session)
                .and()
                .authorizeRequests() // 配置接口权限
                .requestMatchers("/auth/login").permitAll() // 登录接口放行,无需认证
                .requestMatchers("/admin/**").hasRole("ADMIN") // /admin 开头的接口,只有 ADMIN 角色可访问
                .requestMatchers("/user/**").hasRole("USER") // /user 开头的接口,只有 USER 角色可访问
                .anyRequest().authenticated() // 其他所有接口,必须认证才能访问
                .and()
                .oauth2ResourceServer() // 开启 OAuth2 资源服务
                .jwt(); // 使用 JWT 作为令牌

        return http.build();
    }

    // 密码加密器(BCrypt 加密,安全不可逆)
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 认证管理器(负责验证账号密码)
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
}

6.6 JWT 工具类(生成 Token,包含用户角色)

封装生成 JWT Token 的方法,将用户名、角色存入 Token,直接复制:

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.stream.Collectors;

@Component
public class JwtUtil {

    private final JwtEncoder encoder;

    // 构造器注入 JwtEncoder
    public JwtUtil(JwtEncoder encoder) {
        this.encoder = encoder;
    }

    // 生成 JWT Token(包含用户名、角色)
    public String generateToken(Authentication authentication) {
        Instant now = Instant.now(); // 当前时间

        // 获取用户角色(存入 Token,用于后续权限控制)
        String roles = authentication.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(","));

        // 构建 JWT 荷载(存储用户信息)
        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer("http://localhost:8080") // 签发者(自己的项目地址)
                .issuedAt(now) // 签发时间
                .expiresAt(now.plusHours(1)) // 过期时间(1小时)
                .subject(authentication.getName()) // 用户名
                .claim("roles", roles) // 角色信息
                .build();

        // 生成 Token 并返回
        return encoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    }
}

6.7 登录接口(认证获取 Token)

用户登录,验证账号密码,生成并返回 JWT Token,直接复制:

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/auth")
public class AuthController {

    private final AuthenticationManager authenticationManager;
    private final JwtUtil jwtUtil;

    // 构造器注入
    public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil) {
        this.authenticationManager = authenticationManager;
        this.jwtUtil = jwtUtil;
    }

    // 登录接口:POST 请求,参数为 username 和 password
    @PostMapping("/login")
    public Map<String, Object> login(
            @RequestParam String username,
            @RequestParam String password) {

        // 1. 验证账号密码(由 Spring Security 自动验证)
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(username, password)
        );

        // 2. 验证通过,生成 JWT Token
        String token = jwtUtil.generateToken(authentication);

        // 3. 返回 Token 和类型(Bearer 类型)
        return Map.of("token", token, "type", "Bearer");
    }
}

6.8 测试接口(权限控制验证)

编写3个不同权限的接口,测试认证和授权是否生效,直接复制:

import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    // 管理员接口:只有 ADMIN 角色可访问
    @GetMapping("/admin/list")
    public String admin(Authentication authentication) {
        return "管理员专属接口:" + authentication.getName() + ",权限:ADMIN";
    }

    // 普通用户接口:只有 USER 角色可访问
    @GetMapping("/user/info")
    public String user() {
        return "普通用户专属接口";
    }

    // 通用接口:只要登录(认证通过)即可访问
    @GetMapping("/common")
    public String common() {
        return "登录即可访问的通用接口,认证成功!";
    }
}

七、项目测试流程(Postman 实操)

代码写完后,用 Postman 测试:

7.1 登录获取 Token

  1. 打开 Postman,新建 POST 请求,地址:http://localhost:8080/auth/login

  2. 请求参数(表单格式):username=adminpassword=123456

  3. 点击发送,返回结果如下(获取到 Token):

{
    "token": "eyJhbGciOiJSUzI1NiJ9...", // 你的 Token(很长)
    "type": "Bearer"
}

7.2 携带 Token 访问接口

  1. 新建 GET 请求(比如访问管理员接口),地址:http://localhost:8080/admin/list

  2. 请求头添加:Authorization: Bearer 你的Token(注意 Bearer 后面有一个空格);

  3. 点击发送,成功返回结果(认证+授权通过);

  4. 测试其他接口:

    • 访问 /user/info:返回 403 无权限(因为 admin 是 ADMIN 角色,没有 USER 角色);

    • 访问 /common:成功返回(登录即可访问);

    • 不携带 Token 访问任何接口:返回 401 未认证。

测试成功!说明OAuth2.0 + JWT 认证授权已经搭建完成。

八、核心知识点总结

  1. OAuth2.0 是授权协议,JWT 是令牌格式,二者互补,不是替代关系;

  2. OAuth2.0 四大角色:资源所有者、客户端、授权服务器、资源服务器;

  3. 企业常用授权模式:授权码模式(第三方登录)、密码模式(内部系统);

  4. SpringBoot 整合核心三步:引入依赖 → 配置 Security + OAuth2 + JWT → 实现登录 + 权限控制;

  5. OAuth2.0 + JWT 是企业级认证授权标准方案,适配分布式、前后端分离架构,必须掌握!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐