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

如何构建Spring MVC应用实现认证后重定向至原请求URL

Fixing Post-Login Redirect to Original Protected URL in Spring MVC

Great question! This is a super common issue when building authentication flows with Spring Security, and it boils down to not preserving the user's original requested URL before redirecting them to the login page. Let's break down exactly how to fix this, along with the key Spring Security concepts involved.

Key Background: How Spring Security Handles Anonymous Users & Saved Requests

First, let's clarify the mechanics behind the scenes:

  • Anonymous User Detection: Spring Security uses the AnonymousAuthenticationFilter to automatically assign an anonymous authentication token to unauthenticated users. This lets the framework distinguish between unauthenticated requests and fully anonymous traffic, triggering the redirect to login when a protected resource is accessed.
  • Saved Request Storage: When an anonymous user tries to access a protected endpoint, the ExceptionTranslationFilter catches the resulting AuthenticationException and saves the original request details (including the URL) to the user's HttpSession using the key SPRING_SECURITY_SAVED_REQUEST. This is the critical piece we'll leverage to redirect back after login.

Solution 1: Use Spring's Built-In SavedRequestAwareAuthenticationSuccessHandler

Spring Security already has a built-in handler that handles this exact scenario—you might just be overriding it without realizing it. Here's how to configure it properly:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // Define access rules
            .authorizeRequests()
                .antMatchers("/login", "/css/**", "/js/**").permitAll() // Allow public access to login and static assets
                .anyRequest().authenticated() // All other endpoints require authentication
                .and()
            // Configure form login
            .formLogin()
                .loginPage("/login") // Your custom login page URL
                // Use the default handler that automatically reads the saved request
                .successHandler(new SavedRequestAwareAuthenticationSuccessHandler())
                .and()
            // Configure logout (optional but recommended)
            .logout()
                .permitAll();
    }
}

This handler will automatically check the session for the saved request and redirect the user there after successful authentication. If no saved request exists (e.g., the user navigated directly to the login page), it will fall back to the default homepage.

Solution 2: Custom AuthenticationSuccessHandler for Advanced Logic

If you need to add custom behavior (like conditional redirects based on user roles, or validating redirect URLs), you can implement your own handler:

public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler {

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
                                        HttpServletResponse response, 
                                        Authentication authentication) throws IOException {
        
        // Retrieve the saved request from the session
        SavedRequest savedRequest = (SavedRequest) request.getSession().getAttribute("SPRING_SECURITY_SAVED_REQUEST");

        if (savedRequest != null) {
            // Redirect to the original requested URL
            String targetUrl = savedRequest.getRedirectUrl();
            redirectStrategy.sendRedirect(request, response, targetUrl);
        } else {
            // Fallback to default homepage if no saved request exists
            redirectStrategy.sendRedirect(request, response, "/");
        }

        // Optional: Invalidate the saved request to avoid reuse
        request.getSession().removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
    }
}

Then register it in your security config:

.formLogin()
    .loginPage("/login")
    .successHandler(new CustomAuthSuccessHandler())

Solution 3: Stateless/API-Friendly Redirects (No Session)

If you're building a stateless application (like a REST API) where sessions aren't used, you can pass the original URL as a request parameter to the login page:

  1. Add a hidden field to your login form to carry the redirect URL:
<form action="/login" method="post">
    <!-- Your username/password fields -->
    <input type="hidden" name="redirect" value="${param.redirect}">
    <button type="submit">Login</button>
</form>
  1. Update your custom success handler to read and validate this parameter (always validate to prevent open redirect attacks!):
@Override
public void onAuthenticationSuccess(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    Authentication authentication) throws IOException {
    
    String redirectUrl = request.getParameter("redirect");

    // Validate the redirect URL to ensure it's within your domain
    if (StringUtils.hasText(redirectUrl) && isValidRedirectUrl(redirectUrl)) {
        redirectStrategy.sendRedirect(request, response, redirectUrl);
    } else {
        redirectStrategy.sendRedirect(request, response, "/");
    }
}

// Helper method to validate redirect URLs
private boolean isValidRedirectUrl(String url) {
    // Example: Ensure the URL starts with your app's base path
    return url.startsWith("/") && !url.contains("://");
}

Critical Notes to Avoid Issues

  • Ensure Public Access to Login: Always allow anonymous access to your login page and related static assets (CSS, JS) to avoid infinite redirect loops.
  • Clean Up Saved Requests: After redirecting, consider removing the saved request from the session to prevent unexpected behavior if the user logs in again later.
  • Validate Custom Redirects: If using parameter-based redirects, never trust the input blindly—validate that it points to a URL within your application to avoid security risks.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:09:43