Spring Boot前后端分离架构下存储请求URL解决授权重定向问题
解决方案:存储原请求URL并实现自定义重定向
核心思路
由于授权服务器固定重定向到前端仪表盘,我们需要在用户触发认证跳转前拦截请求,保存原请求URL;待授权服务器回调至仪表盘时,读取保存的URL完成二次跳转,同时确保令牌能正常用于后端通信。
具体实现步骤
1. 拦截未认证请求,存储原URL
通过Spring Security的AuthenticationEntryPoint自定义认证入口,在跳转授权服务器前将原请求URL存入会话:
@Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { // 排除授权回调端点,避免误存回调URL if (!request.getRequestURI().equals("/oauth2/callback")) { // 拼接完整请求URL(含参数)并存入session String fullUrl = request.getRequestURL().append("?").append(request.getQueryString()).toString(); request.getSession().setAttribute("ORIGINAL_REQUEST_URL", fullUrl); } // 重定向到授权服务器认证端点 response.sendRedirect("/oauth2/authorization/your-provider-id"); } }
在Spring Security配置中注册该入口:
@Configuration @EnableWebSecurity public class SecurityConfig { private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; public SecurityConfig(CustomAuthenticationEntryPoint customAuthenticationEntryPoint) { this.customAuthenticationEntryPoint = customAuthenticationEntryPoint; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2Login(oauth2 -> oauth2.defaultSuccessUrl("/dashboard")) // 授权服务器固定回调至仪表盘 .exceptionHandling(ex -> ex.authenticationEntryPoint(customAuthenticationEntryPoint)); return http.build(); } }
2. 在仪表盘端点处理二次重定向
授权回调至/dashboard时,读取会话中存储的原URL,存在则跳转至该URL,否则停留仪表盘:
@Controller public class DashboardController { @GetMapping("/dashboard") public String dashboard(HttpServletRequest request) { String originalUrl = (String) request.getSession().getAttribute("ORIGINAL_REQUEST_URL"); if (originalUrl != null) { // 清除session中的存储,避免重复跳转 request.getSession().removeAttribute("ORIGINAL_REQUEST_URL"); return "redirect:" + originalUrl; } return "dashboard"; } }
3. 令牌用于后端通信的处理
Spring Security OAuth2客户端会自动管理令牌的获取与存储,调用后端接口时可通过注解直接注入授权客户端,携带令牌发起请求:
@RestController public class BackendApiClient { @Autowired private RestTemplate restTemplate; @GetMapping("/fetch-backend-data") public ResponseEntity<String> fetchData(@RegisteredOAuth2AuthorizedClient("your-provider-id") OAuth2AuthorizedClient client) { String token = client.getAccessToken().getTokenValue(); HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(token); HttpEntity<String> entity = new HttpEntity<>(headers); return restTemplate.exchange("http://backend-service/api/data", HttpMethod.GET, entity, String.class); } }
注意事项
- 集群部署时需使用Redis等分布式会话存储,避免原URL丢失。
- 若原请求URL包含敏感参数,需过滤敏感字段后再存储,或加密存储。
- 需确保授权回调端点被正确排除,防止误存回调URL。
内容的提问来源于stack exchange,提问作者Syed Iftekharuddin
相关产品推荐
相关产品推荐

