You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Google OAuth2实现API服务的JWT请求认证

解决方案:Spring Security OAuth2 转 JWT 实现API认证

问题根源

你当前的配置基于会话认证:浏览器登录后通过Cookie维护会话状态,所以能正常访问;但Postman用Google的Bearer Token请求时,服务端不识别该Token——既没配置OAuth2资源服务器验证第三方Token,也没生成自有JWT返回给客户端,导致401未授权。

实现步骤

1. 添加核心依赖

以Maven为例,引入OAuth2资源服务器和JWT相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>

2. 配置资源服务器验证Google Token

在application.yml中补充资源服务器配置,让服务端能校验Google签发的Bearer Token:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: ${GOOGLE_CLIENT_ID}
            client-secret: ${GOOGLE_CLIENT_SECRET}
      resourceserver:
        jwt:
          issuer-uri: https://accounts.google.com

3. 自定义认证成功处理器生成自有JWT

OAuth2登录成功后,生成服务端自有JWT返回给客户端,替代会话机制:

@Component
public class CustomAuthSuccessHandler implements OAuth2AuthenticationSuccessHandler {

    private final JwtEncoder jwtEncoder;

    public CustomAuthSuccessHandler(JwtEncoder jwtEncoder) {
        this.jwtEncoder = jwtEncoder;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, OAuth2AuthenticationToken authToken) throws IOException {
        // 从Google认证信息中获取用户邮箱,查询数据库中已创建的用户
        String userEmail = authToken.getPrincipal().getName();
        User dbUser = getUserByEmail(userEmail);

        // 构建JWT声明
        Instant now = Instant.now();
        JWTClaimsSet claims = JWTClaimsSet.builder()
                .issuer("your-api-service")
                .subject(dbUser.getId().toString())
                .issuedAt(now)
                .expiresAt(now.plusSeconds(36000)) // 10小时有效期
                .claim("email", dbUser.getEmail())
                .build();

        // 生成JWT Token
        JwtEncoderParameters params = JwtEncoderParameters.from(JWSHeader.with(Algorithm.HS256).build(), claims);
        String jwtToken = jwtEncoder.encode(params).getTokenValue();

        // 返回Token给客户端(JSON格式)
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), Map.of("access_token", jwtToken));
    }

    // 替换为你实际的数据库查询逻辑
    private User getUserByEmail(String email) {
        // 示例:从数据库查询用户
        return new User();
    }
}

4. 配置JWT编码器

配置签名JWT的编码器(生产环境建议改用非对称加密,如RSA):

@Configuration
public class JwtConfig {

    @Value("${jwt.secret}")
    private String secretKey;

    @Bean
    public JwtEncoder jwtEncoder() {
        SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
        return new NimbusJwtEncoder(new ImmutableSecret<>(secretSpec));
    }
}

在application.yml中添加JWT密钥:

jwt:
  secret: your-strong-32-character-secret-key-here # 生产环境需用安全方式管理密钥

5. 更新SecurityFilterChain配置

禁用会话,启用无状态JWT认证,并绑定自定义成功处理器:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomAuthSuccessHandler authSuccessHandler;

    public SecurityConfig(CustomAuthSuccessHandler authSuccessHandler) {
        this.authSuccessHandler = authSuccessHandler;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) // API服务通常禁用CSRF
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 无状态,不依赖会话
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/login/**").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth2 -> oauth2
                        .successHandler(authSuccessHandler) // 登录成功返回JWT
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter())) // 转换JWT为认证信息
                );
        return http.build();
    }

    // 自定义JWT转换器,将声明转为权限信息
    private JwtAuthenticationConverter jwtConverter() {
        JwtGrantedAuthoritiesConverter authorityConverter = new JwtGrantedAuthoritiesConverter();
        authorityConverter.setAuthorityPrefix("ROLE_");

        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(authorityConverter);
        return converter;
    }
}

6. 客户端API请求方式

用户通过/login完成Google登录后,会收到服务端返回的JWT Token。后续请求API时,在请求头中携带:

Authorization: Bearer <your-api-jwt-token>

服务端将验证该Token并完成认证。

内容的提问来源于stack exchange,提问作者bosowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:25:25