1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Spring Security】ログインページにカスタムクエリパラメータを追加してもうまく動作しなかった件

1
Last updated at Posted at 2025-08-10

はじめに

ログインページを自作して、渡したクエリパラメータの値によって表示を一部いじりたい、というユースケースで問題が発生しました。

問題の外観としては、/login?sample=hogeにアクセスしたとき、/loginにリダイレクトされてしまう、というものです。

結論から

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
            throws Exception {
        http
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/css/**", "/error/**").permitAll()
                        // ★ sampleパラメータがついたURLを限定的に許可するRequestMatcherの追加
                        .requestMatchers(new CustomLoginPageRequestMatcher()).permitAll()
                        .anyRequest().authenticated())
                .formLogin(form -> form.loginPage("/login").permitAll());

        return http.build();
    }

    // ★ sampleパラメータがついたURLを許可するMatcherの定義
    private static final class CustomLoginPageRequestMatcher implements RequestMatcher {

        private static final Set<String> ALLOWED_PARAMS = Set.of("sample", "error", "logout");

        private final RequestMatcher pathDelegater = request -> "/login".equals(request.getServletPath())
                && "GET".equalsIgnoreCase(request.getMethod());

        @Override
        public boolean matches(HttpServletRequest request) {
            // ★ /loginに対してGETでアクセスしたとき以外はマッチしない
            if (!pathDelegater.matches(request)) {
                return false;
            }

            // ★ sample, error, logout以外がついていたらfalseを返す
            return request.getParameterMap().keySet().stream()
                    .allMatch(ALLOWED_PARAMS::contains);
        }
    }

}

/loginに対して、認証なしでどんなクエリパラメータを受け入れても良いなら下記でも可

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
            throws Exception {
        http
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/css/**", "/error/**", "/login").permitAll()
                        .anyRequest().authenticated())
                .formLogin(form -> form.loginPage("/login").permitAll());

        return http.build();
    }

}

原因

http.formLogin(form -> form.loginPage("/login").permitAll());

formLoginによるログインページのアクセス制御が、以下のURLしかアクセス許可されないことによって発生します。

  • /login
  • /login?error
  • /login?logout

/login?sample=hogeは上記のURLにマッチしないため、アクセスには認証を必要とします。ログインページにアクセスしているという状況なので、当然認証されていないためアクセス拒否され、クエリパラメータのついていない/loginにリダイレクトされます。

ちなみにSpring Securityのドキュメントには、このような形でアクセス許可されるURLについて記載があります。

この値を更新すると、他の多くのデフォルト値にも影響します。例: formLogin() のみが指定された場合のデフォルト値は次のとおりです。

  • /login GET - the login form
  • /login POST - process the credentials and if valid authenticate the user
  • /login?error GET - redirect here for failed authentication attempts
  • /login?logout GET - redirect here after successfully logging out

"/authenticate" がこのメソッドに渡された場合、以下に示すようにデフォルトが更新されます。

  • /authenticate GET - the login form
  • /authenticate POST - process the credentials and if valid authenticate the user
  • /authenticate?error GET - redirect here for failed authentication attempts
  • /authenticate?logout GET - redirect here after successfully logging out

余談ですが、TRACEログを眺めると、/login?sample=hogeがアクセス拒否され、/loginへリダイレクトされる様子が観察できます。

2025-08-11T01:17:36.393+09:00 DEBUG 1126860 --- [nio-9000-exec-4] o.s.security.web.FilterChainProxy        : Securing GET /login?sample=hoge

...

2025-08-11T01:17:36.396+09:00 TRACE 1126860 --- [nio-9000-exec-4] o.s.s.w.a.ExceptionTranslationFilter     : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=69BADCDB51A0533BE717B1191BCFAF2B], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied

org.springframework.security.authorization.AuthorizationDeniedException: Access Denied
        at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:99) ~[spring-security-web-6.5.2.jar:6.5.2]
        at 
        ...
        
2025-08-11T01:17:36.399+09:00 DEBUG 1126860 --- [nio-9000-exec-4] o.s.s.w.s.HttpSessionRequestCache        : Saved request http://127.0.0.1:9000/login?sample=hoge&continue to session
2025-08-11T01:17:36.399+09:00 DEBUG 1126860 --- [nio-9000-exec-4] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://127.0.0.1:9000/login

おわりに

今回は、Spring SecurityのHttpSecurity.formLoginを利用したときに遭遇した問題について取り上げました。
同じような問題に遭遇した方の参考になれば幸いです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?