如何自定义SpringSocial Facebook授权取消后的access_denied跳转URL?
刚好我之前也处理过类似的需求,给你两个实用的方案,你可以根据项目的实际情况选择:
方案一:重写ProviderSignInController的oauth2ErrorCallback方法
SpringSocial的ProviderSignInController里的oauth2ErrorCallback方法是protected的,所以我们可以通过继承这个类,重写该方法来实现自定义跳转:
首先创建自定义的Controller类:
import org.springframework.social.connect.web.ProviderSignInController; import org.springframework.social.oauth2.OAuth2Error; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.servlet.view.RedirectView; public class CustomProviderSignInController extends ProviderSignInController { // 必须调用父类构造方法,传入所需的核心依赖 public CustomProviderSignInController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository, SignInService signInService) { super(connectionFactoryLocator, connectionRepository, signInService); } @Override protected RedirectView oauth2ErrorCallback(String providerId, OAuth2Error oauth2Error, NativeWebRequest request) { // 替换成你的自定义页面路径,比如"/access-denied-page" return new RedirectView("/access-denied-page", true); } }
接下来在你的Spring配置类中,注册这个自定义的Controller,替换掉默认的ProviderSignInController:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.social.connect.ConnectionFactoryLocator; import org.springframework.social.connect.ConnectionRepository; import org.springframework.social.connect.web.SignInService; @Configuration public class SocialConfig { @Bean public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository, SignInService signInService) { return new CustomProviderSignInController(connectionFactoryLocator, connectionRepository, signInService); } }
这种方案的好处是精准对应授权取消的场景,直接修改源头逻辑,不会影响其他请求。
方案二:用拦截器拦截/signin的错误请求
如果你不想修改原有Controller的继承关系,也可以通过拦截器来捕获带有access_denied错误的请求,并重定向到自定义页面:
先创建一个拦截器类:
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @Component public class AccessDeniedRedirectInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String errorParam = request.getParameter("error"); // 匹配access_denied错误 if ("access_denied".equals(errorParam)) { // 跳转到自定义页面 response.sendRedirect("/custom-access-denied"); return false; // 终止原有请求流程 } return true; // 其他请求正常放行 } }
然后在WebMvc配置类中注册这个拦截器,让它拦截/signin路径:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { private final AccessDeniedRedirectInterceptor accessDeniedRedirectInterceptor; // 构造注入拦截器 public WebMvcConfig(AccessDeniedRedirectInterceptor accessDeniedRedirectInterceptor) { this.accessDeniedRedirectInterceptor = accessDeniedRedirectInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(accessDeniedRedirectInterceptor) .addPathPatterns("/signin"); // 只拦截/signin请求 } }
这个方案的优势是无需修改原有社交登录的核心逻辑,通过拦截器实现跳转,比较灵活,适合快速修改的场景。
内容的提问来源于stack exchange,提问作者Clayton K. N. Passos
相关产品推荐
相关产品推荐

