Spring Security OAuth2认证时DefaultOidcUser无法转CustomOAuth2User如何解决?
错误原因
你使用的OAuth2认证提供商支持OIDC(OpenID Connect)协议,Spring Security完成认证后返回的身份主体(Principal)为DefaultOidcUser类型,它属于OAuth2User的子类,但你没有对其做自定义包装,因此无法直接强转为自行实现的CustomOAuth2User类。
解决方案
提供两种可行方案,可根据需求选择:
方案一:快速修复(直接修改认证成功处理器)
无需额外新增类,直接修改成功处理器代码,兼容所有OAuth2User子类即可:
.successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 统一包装原生OAuth2用户为自定义类型 CustomOAuth2User oauthUser = new CustomOAuth2User((OAuth2User) authentication.getPrincipal()); userAuthService.processOAuthPostLogin(oauthUser.getEmail()); response.sendRedirect("/list"); } })
方案二:规范扩展(自定义用户加载服务)
符合Spring Security扩展规范,后续自定义用户属性、权限逻辑更方便:
- 实现自定义用户加载服务,分别处理普通OAuth2和OIDC类型用户
// 处理普通OAuth2用户 public class CustomOAuth2UserService extends DefaultOAuth2UserService { @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { OAuth2User oAuth2User = super.loadUser(userRequest); return new CustomOAuth2User(oAuth2User); } } // 处理OIDC类型用户 public class CustomOidcUserService extends OidcUserService { @Override public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { OidcUser oidcUser = super.loadUser(userRequest); return new CustomOAuth2User(oidcUser); } }
- 修改
CustomOAuth2User实现OidcUser接口,兼容OIDC类型用户
public class CustomOAuth2User implements OidcUser { private OAuth2User oauth2User; public CustomOAuth2User(OAuth2User oauth2User) { this.oauth2User = oauth2User; } // 原有方法保持不变 @Override public Map<String, Object> getAttributes() { return oauth2User.getAttributes(); } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return oauth2User.getAuthorities(); } @Override public String getName() { return oauth2User.getAttribute("name"); } public String getEmail() { return oauth2User.<String>getAttribute("email"); } // 新增OidcUser接口实现方法 @Override public Map<String, Object> getClaims() { return oauth2User instanceof OidcUser ? ((OidcUser) oauth2User).getClaims() : Collections.emptyMap(); } @Override public OidcIdToken getIdToken() { return oauth2User instanceof OidcUser ? ((OidcUser) oauth2User).getIdToken() : null; } @Override public OidcUserInfo getUserInfo() { return oauth2User instanceof OidcUser ? ((OidcUser) oauth2User).getUserInfo() : null; } }
- 在WebSecurityConfig的OAuth2登录配置中注入自定义服务
http .oauth2Login() .userInfoEndpoint() .userService(new CustomOAuth2UserService()) .oidcUserService(new CustomOidcUserService()) .and() .successHandler(// 你原有成功处理器代码,直接强转CustomOAuth2User即可)
内容的提问来源于stack exchange,提问作者Abdelrahman Ragab
相关产品推荐
相关产品推荐

