Spring Security 中重定向已登錄用户

Spring Security
Remote
0
05:28 AM · Nov 30 ,2025

1. 概述

用户在已登錄狀態下,經常無法訪問登錄頁面。 常見的做法是將用户重定向到另一個頁面,通常是在登錄後應用程序的起始點。

在本教程中,我們將探討使用 Spring Security 實現此解決方案的多種方法。

此外,為了更快速地實現登錄功能,我們可以參考 這篇文章。

2. 身份驗證驗證

首先,我們需要一種驗證身份驗證的方法。

換句話説,我們需要從 SecurityContext 中獲取身份驗證詳情,並驗證用户是否已登錄

private boolean isAuthenticated() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication == null || AnonymousAuthenticationToken.class.
      isAssignableFrom(authentication.getClass())) {
        return false;
    }
    return authentication.isAuthenticated();
}

我們將在此後所有負責重定向的組件中使用它。

3. 從登錄控制器重定向

實現我們的目標最簡單的方法是,在控制器中定義登錄頁面的端點。

我們還需要在用户已認證時返回特定的頁面,否則返回登錄頁面:

@GetMapping("/loginUser")
public String getUserLoginPage() {
    if (isAuthenticated()) {
        return "redirect:userMainPage";
    }
    return "loginUser";
}

4. 使用攔截器

通過 URI 上的攔截器,另一種重定向用户的方式是登錄頁面的攔截器。

攔截器將在請求到達控制器之前攔截請求。因此,我們可以根據身份驗證情況決定是否允許其繼續,或者阻止其並返回重定向響應。

如果用户已認證,我們需要修改響應中的兩項內容:

  • 設置狀態碼為 HttpStatus.SC_TEMPORARY_REDIRECT
  • 添加 Location 標頭,包含重定向 URL

最後,我們將通過返回 false 終止執行鏈:

public class LoginPageInterceptor implements HandlerInterceptor {
    UrlPathHelper urlPathHelper = new UrlPathHelper();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if ("/loginUser".equals(urlPathHelper.getLookupPathForRequest(request)) && isAuthenticated()) {
            String encodedRedirectURL = response.encodeRedirectURL(
              request.getContextPath() + "/userMainPage");
            response.setStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
            response.setHeader("Location", encodedRedirectURL);

            return false;
        } else {
            return true;
        }
    }

    // isAuthenticated method 
}

我們也需要將攔截器添加到 Spring MVC 生命週期

@Configuration
public class LoginRedirectMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginPageInterceptor());
    }
}

我們也可以使用 Spring 的基於 XML 模式來實現相同的功能:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/loginUser"/>
        <bean class="com.baeldung.loginredirect.LoginPageInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

5. 使用過濾器

類似於,我們可以實現一個 Spring 過濾器。

該過濾器可以直接應用於 SecurityContext,利用 Spring Security 的過濾器鏈。因此,它可以在身份驗證創建後立即攔截請求。

public class LoginPageFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;

        if (isAuthenticated() && "/loginUser".equals(servletRequest.getRequestURI())) {

            String encodedRedirectURL = ((HttpServletResponse) response).encodeRedirectURL(
              servletRequest.getContextPath() + "/userMainPage");

            servletResponse.setStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
            servletResponse.setHeader("Location", encodedRedirectURL);
        }

        chain.doFilter(servletRequest, servletResponse);
    }
    // isAuthenticated 方法
}

我們需要在過濾器鏈中將過濾器添加到 UsernamePasswordAuthenticationFilter 之後。

此外,我們需要為登錄頁 URI 啓用過濾器鏈,以授權該請求:

@Configuration
@EnableWebSecurity
public class LoginRedirectSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.addFilterAfter(new LoginPageFilter(), UsernamePasswordAuthenticationFilter.class)
            .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> 
                          authorizationManagerRequestMatcherRegistry.requestMatchers("/loginUser").permitAll()
        // Other security configuration
    }
}

最後,如果選擇使用 XML 配置,則可以定義過濾器的 Bean,並在安全 HTTP 標籤中將其添加到過濾器鏈中:

<beans:bean id="loginPageFilter" class="com.baeldung.loginredirect.LoginPageFilter"/>

<security:http pattern="/**" use-expressions="true" auto-config="true">
    <security:intercept-url pattern="/loginUser" access="permitAll"/>
    <security:custom-filter after="BASIC_AUTH_FILTER" ref="loginPageFilter"/>
</security:http>

有關如何為 Spring Security 創建自定義過濾器的快速教程,請參見此處。

6. 結論

在本教程中,我們探討了如何使用 Spring Security 將已登錄的用户從登錄頁面重定向的多種方法。

另一個可能對您有幫助的教程是“使用 Spring Security 在登錄後重定向到不同頁面”,其中我們學習瞭如何將不同類型的用户重定向到特定頁面。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.