aya0724masa
@aya0724masa

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

spring-boot-starter-securityの依存関係を追加すると、ページ表示できなくなる

解決したいこと

Spring bootでWebアプリを作っています。
ユーザーのログインページを作りましたが、
spring-boot-starter-securityの依存関係を追加すると、HTTPリクエストエラーになり、ログインページを表示できません。
依存関係を追加しないと、正常に画面表示できます。
依存関係を追加した状態で、正常に画面表示できるようにしたいです。

発生している問題・エラー

ログインページに遷移しようとすると、以下のエラーになります。

This page isn’t working
localhost redirected you too many times.
Try deleting your cookies.
ERR_TOO_MANY_REDIRECTS

開発者ツールでリクエストを確認すると、大量のリクエストが送られていて、全て302エラーになっています。

該当するソースコード

以下のように依存関係を追加しています。

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

自分で試したこと

SecurityConfigクラスを作成し、
/loginと/registerのURLは認証されていなくてもアクセスできるように設定しているのですが、正常に画面遷移できません。

package com.reading.tracker.readingtracker.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig{

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/register", "/login").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login").permitAll()
                .defaultSuccessUrl("/register")
            )
            .logout(logout -> logout
                .permitAll()
                .logoutSuccessUrl("/login")
            );

        return http.build();
    }
}
0

2Answer

エラーの内容の通り、リダイレクトがループした影響でページが表示できていません。

開発者ツールでリクエストを確認すると、大量のリクエストが送られていて、全て302エラーになっています。

この開発者ツールのスクリーンキャプチャを貼っていただくことは可能でしょうか?
また、

ユーザーのログインページを作りましたが、

依存関係を追加しないと、正常に画面表示できます。

ユーザーのログインページのControllerのソースコードもお見せいただけますでしょうか。

1Like

Comments

  1. @aya0724masa

    Questioner

    ご確認ありがとうございます。

    開発者ツールは以下のようになっています。
    Screenshot 2024-11-05 at 23.06.02.png

    Controllerは下記のコードです。

    package com.reading.tracker.readingtracker.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import com.reading.tracker.readingtracker.service.UserService;
    
    @Controller
    public class UserController {
    
        @Autowired
        UserService userService;
    
        @GetMapping("/register")
        public String showRegisterPage() {
            return "register";
        }
    
        @PostMapping("/register")
        public String registerUser(@RequestParam String email, @RequestParam String password, Model model) {
            userService.registerUser(email, password);
            model.addAttribute("message", "Registration successful! Please login.");
            return "register";
        }
    
        @GetMapping("/login")
        public String showLoginPage() {
            return "login";
        }
    
        @PostMapping("/login")
        public String loginUser(@RequestParam String email, @RequestParam String password) {
            if (userService.loginUser(email, password).isPresent()) {
                return "redirect:home";
            }else {
                return "login";
            }
        }
    }
    

    どこか問題ありますでしょうか?

  2. スクリーンショットの添付、ありがとうございます。

    恐らくなのですが、login.htmlを表示する過程で何か例外が発生しているのではないでしょうか。
    現在/errorへのアクセスは制限されている状態ですので、/loginへの遷移自体に問題がある場合以下のようにループが発生してしまいます。

    1. login.htmlを表示する過程に何か問題がありエラーが発生
    2. error.htmlの表示を試行(Springの標準の仕様で例外発生時はerror.htmlを表示しようとします)
    3. SecurityConfig.javaでは/errorへのリソースアクセスは許可されておらず、/loginへリダイレクトさせる
    4. login.htmlを表示する過程に何か問題がありエラーが発生
    5. (以下ループ)

    まずは情報収集のために、SecurityConfig.java/errorへのアクセスも許可するようにしてみてください。

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig{
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                    .csrf(csrf -> csrf.disable())
                    .authorizeHttpRequests(auth -> auth
    -                        .requestMatchers("/register", "/login").permitAll()
    +                        .requestMatchers("/register", "/login", "/error").permitAll()
                            .anyRequest().authenticated()
                    )
                    .formLogin(form -> form
                            .loginPage("/login").permitAll()
                            .defaultSuccessUrl("/register")
                    )
                    .logout(logout -> logout
                            .permitAll()
                            .logoutSuccessUrl("/login")
                    );
    
            return http.build();
        }
    }
    
  3. @aya0724masa

    Questioner

    errorへのアクセス許可をすると、以下のエラー画面が表示されました。
    循環遷移されているようです。
    Screenshot 2024-11-06 at 8.39.46.png

  4. スタックトレースにはあまりヒントがありませんね…

    私の方でも@aya0724masa様と同じ内容のSecurityConfig.javaを使い検証用のプロジェクトを作成して動かしていますが、正常に/loginへアクセスできています。
    なのでSpringSecurityとはまた別の問題かと見受けられます。

    差し支えなければpom.xmllogin.htmlの内容、またsrcディレクトリ配下の構造がわかるスクリーンショット(Eclipseを使用されていればパッケージエクスプローラのスクショ) などもご提供いただけますでしょうか。

    私の方でも現象を再現できればもう少しお役立てできそうです。

  5. @aya0724masa

    Questioner

    @tomdog735 様の環境だとアクセスできるんですね...
    確かにどこか別のところでおかしくなってる気がします。

    以下にそれぞれ、コードを提示したので、ご確認いただきたいです。

    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>3.3.5</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.reading.tracker</groupId>
    	<artifactId>readingtracker</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>readingtracker</name>
    	<description>Demo project for Spring Boot</description>
    	<url/>
    	<licenses>
    		<license/>
    	</licenses>
    	<developers>
    		<developer/>
    	</developers>
    	<scm>
    		<connection/>
    		<developerConnection/>
    		<tag/>
    		<url/>
    	</scm>
    	<properties>
    		<java.version>17</java.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-security</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.session</groupId>
    			<artifactId>spring-session-core</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-devtools</artifactId>
    			<scope>runtime</scope>
    			<optional>true</optional>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<optional>true</optional>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.security</groupId>
    			<artifactId>spring-security-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.postgresql</groupId>
    			<artifactId>postgresql</artifactId>
    			<version>42.7.4</version>
    		</dependency>
    		<dependency>
    			<groupId>me.paulschwarz</groupId>
    			<artifactId>spring-dotenv</artifactId>
    			<version>4.0.0</version>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    				<configuration>
    					<excludes>
    						<exclude>
    							<groupId>org.projectlombok</groupId>
    							<artifactId>lombok</artifactId>
    						</exclude>
    					</excludes>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    
    login.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
    </head>
    
    <body>
        <h1>Login</h1>
        <form action="login" method="post">
            <label>Email: <input type="email" name="email" required></label><br>
            <label>password: <input type="password" name="password" required></label>
            <button type="submit">Login</button>
        </form>
    </body>
    
    </html>
    

    また、ディレクトリ構造は以下のようになっています。
    Screenshot 2024-11-06 at 19.42.36.png

  6. ソースコードとスクリーンショットのご提供、誠にありがとうございます。
    私の環境に取り込んだところ、@aya0724masa様と同じ現象を再現させることができました。

    先に原因と解決案を記載させていただきます。

    直接的な原因

    • login.htmlの配置先がsrc/resources/staticではなくsrc/resources/templatesであった為
    • 且つ、UserControllerの各メソッドの戻り値で指定しているファイル名に拡張子.htmlが省略されていた為

    解決案(どちらか一方)

    1. login.html含むhtmlファイル全てをsrc/resources/staticに移動し、UserControllerの戻り値を拡張子含む完全なファイル名に修正する
    2. または、Thymeleaf等のテンプレートエンジンを利用する (この場合htmlファイルの配置先とUserControllerは修正不要になります。)

    pom.xmlの内容を拝見しますとThymeleaf等のテンプレートエンジンを使用されていないようですが、
    この場合SpringBootはControllerで指定されたhtmlファイルをsrc/resources/staticから探そうとします。
    また、htmlファイルの拡張子を省略することもできません。
    htmlファイルをstatic配下に置き、Controllerを修正することで私の環境ではloginページへのアクセスに成功しました。

        @GetMapping("/login")
        public String showLoginPage() {
    -       return "login";
    +       return "login.html";
        }
    

    余談

    1点だけ気になった点としまして、

    依存関係を追加しないと、正常に画面表示できます。

    私の環境ではSpringSecurityを外しても画面表示ができませんでした。
    もしかしますと、どこかの過程でThymeleafの依存関係をpom.xmlから消してしまったのではないでしょうか。
    飽くまで推測ですが、もし心当たりなどありましたらご確認ください。

    以上、参考になりましたら幸いです。

  7. @aya0724masa

    Questioner

    原因の解明ありがとうございます。
    解決案2のThymeleafの依存関係の追加ではアクセス成功しましたが、1の方法ではアクセスできませんでした。
    まだ、どこか環境差異があるかもしれませんが、2の方法でアクセスできるようになったので、大変助かりました。ありがとうございます。

    また、pom.xmlの履歴を見ましたが、Thymeleafを消してしまったようなところは見られませんでした。

Spring Securityでは、デフォルトで提供されるログインフォームのパスが /loginであり、カスタムのログインフォームと同じパスの場合、競合が発生する可能性があります。一度Spring Securityのログイン機能を無効化してみるのはいかがでしょうか?

@Configuration
@EnableWebSecurity
public class SecurityConfig{
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                       .requestMatchers("/register", "/login").permitAll()
                        .anyRequest().authenticated()
                )
+                .formLogin(form -> form.disable())
                .logout(logout -> logout
                        .permitAll()
                        .logoutSuccessUrl("/login")
                );
        return http.build();
    }
}
 .formLogin(form -> form.disable())

韓国人なので日本語翻訳を 돌렸습니다。文脈が変かもしれません。

0Like

Comments

  1. @aya0724masa

    Questioner

    コードの修正案をいただき、ありがとうございます。
    ただ、コードを修正しても、挙動は変わりませんでした。
    @tomdog735 さんの言うようにSecurityConfig以外がおかしいのかもしれません。

    Screenshot 2024-11-06 at 19.46.44.png

Your answer might help someone💌