Spring Security 6整合Discord作为OAuth2身份提供商遇故障求助
Spring Security 6 整合 Discord OAuth2 完整配置方案
1. 修复 Token 端点 HTTP 400 问题
Discord 的 OAuth2 Token 端点强制要求通过Basic Auth传递客户端ID和密钥,Spring Security 6 默认不会自动适配这个规则,只需在配置里显式指定认证方式即可,无需自定义拦截器:
application.yaml 核心配置
spring: security: oauth2: client: registration: discord: client-id: 你的Discord客户端ID client-secret: 你的Discord客户端密钥 client-authentication-method: client_secret_basic authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" scope: identify, email provider: discord: authorization-uri: https://discord.com/api/oauth2/authorize token-uri: https://discord.com/api/oauth2/token user-info-uri: https://discord.com/api/users/@me user-name-attribute: id
关键配置是client-authentication-method: client_secret_basic,Spring Security 会自动生成 Basic Auth 头并传递到 Token 端点。
2. 修复 JSON 解析失败问题
Discord 返回的 Token 响应采用蛇形命名(如access_token、refresh_token),Spring Security 默认转换器未适配该格式,导致解析为空。需自定义响应转换器:
自定义 Token 响应转换器配置类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; @Configuration public class DiscordOAuth2Config { @Bean public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeTokenResponseClient() { DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); OAuth2AccessTokenResponseHttpMessageConverter converter = new OAuth2AccessTokenResponseHttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); // 强制使用蛇形命名解析响应JSON objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); converter.setObjectMapper(objectMapper); tokenResponseClient.setAccessTokenResponseConverter(converter); return tokenResponseClient; } }
3. Vaadin 适配配置
需确保 OAuth2 登录回调路径不被 Vaadin 路由拦截,同时在 Spring Security 中放行相关路径:
Spring Security 过滤链配置
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @EnableWebSecurity public class SecurityConfig { private final OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> tokenResponseClient; public SecurityConfig(OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> tokenResponseClient) { this.tokenResponseClient = tokenResponseClient; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/login/**", "/oauth2/**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .tokenEndpoint(token -> token .accessTokenResponseClient(tokenResponseClient) ) ); return http.build(); } }
验证示例
在 Vaadin 视图中获取 Discord 用户信息:
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.core.user.OAuth2User; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; @Route("") public class MainView extends VerticalLayout { public MainView(@AuthenticationPrincipal OAuth2User oauth2User) { add("Discord用户ID: " + oauth2User.getAttribute("id")); add("Discord用户名: " + oauth2User.getAttribute("username")); add("邮箱: " + oauth2User.getAttribute("email")); } }
内容的提问来源于stack exchange,提问作者klenkes74
相关产品推荐
相关产品推荐

