@tongyu

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Spring Securityでログイン画面を管理者とユーザーで分けて作成したい。

実現したいこと

現在、下記のことを実装したいと考えていますがうまくいきません。
Spring Securityのバージョンが6になり、最新情報がなかなか見つからず困っております。
アドバイスを頂けると助かります。

  • 管理者側のログイン画面とユーザーログイン画面を別々で用意する。
  • ログインに成功すると管理者用のトップ画面とユーザー用のトップ画面に遷移する。
  • 管理者はどちらのログイン画面からもログインでき、どちらの機能も使用することができる。
  • ユーザ側が管理者画面からログインしようとすると、ユーザーのログイン画面に遷移する。

発生している問題・エラー(長いため最初のほうをコピーして貼り付けています。)

  1. 管理者ログイン機能の/admin/loginからはログインすることが可能。
    しかし、ユーザーも/admin/loginからログインすることができてしまう。
    ログイン成功時は、管理者は管理者用トップ画面に遷移。ユーザーはユーザーのトップ画面に遷移。
  2. ユーザーログイン機能の/user/loginからはログインすることができない。
    下記のPOSTに関するエラーが出てしまう。

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Jul 26 10:40:36 JST 2023
There was an unexpected error (type=Method Not Allowed, status=405).
Method 'POST' is not supported.
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported
	at org.springframework.web.servlet.support.WebContentGenerator.checkRequest(WebContentGenerator.java:381)
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:164)
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:51)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365)
	at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
	at 

WARN[0;39m [35m212088[0;39m [2m---[0;39m [2m[nio-8080-exec-8][0;39m [36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported]

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコードJava

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {
	
	@Autowired
	private AdminLoginUserDetailsService adminLoginUserDetailsService;
	
	@Autowired
	private UserLoginUserDetailsService userLoginUserDetailsService;
	
	// ログイン成功後のリダイレクト先を設定
    @Bean
    AuthenticationSuccessHandler successHandler() {
        return new SimpleUrlAuthenticationSuccessHandler() {
            @Override
            protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
                // ログインユーザーのロールを取得する
                Authentication auth = SecurityContextHolder.getContext().getAuthentication();
                String role = auth.getAuthorities().toString();

                // デフォルトのリダイレクト先
                String targetUrl = "/login?error";
                if(role.contains("ROLE_ADMIN")) {
                	if(request.getRequestURI().equals("/admin/login")) {
                		targetUrl = "/admin/notices";
                	} else {
                		targetUrl = "/user/login";
                	}
                } else if(role.contains("ROLE_USER")) {
                    targetUrl = "/user/notices";
                }
                return targetUrl;
            }
        };
    }
    
 // 管理者ログイン用のセキュリティ設定
    @Bean
    @Order(1)
    SecurityFilterChain adminSecurityFilterChain(HttpSecurity http) throws Exception {
        http
        .authorizeHttpRequests((requests) -> requests
        		.requestMatchers("/admin/login", "/user/login").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin((form) -> form
        		.loginProcessingUrl("/admin/login")
                .usernameParameter("empNum")
                .loginPage("/admin/login")
                .successHandler(successHandler())
                .permitAll()
            )
            .userDetailsService(adminLoginUserDetailsService)
            .logout((logout) -> logout.permitAll());
        return http.build();
    }

 
 // ユーザーログイン用のセキュリティ設定
    @Bean
    @Order(2)
    SecurityFilterChain userSecurityFilterChain(HttpSecurity http) throws Exception {
        http
        .authorizeHttpRequests((requests) -> requests
    		.requestMatchers("/user/login", "/admin/login").permitAll()
            .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
            .requestMatchers(HttpMethod.POST, "/user/login").permitAll()
            .anyRequest().authenticated()
        )
            .formLogin((login) -> login
        		.loginProcessingUrl("/user/login")
                .usernameParameter("empNum")
                .loginPage("/user/login")
                .successHandler(successHandler())
                .permitAll()
            )
            .userDetailsService(userLoginUserDetailsService)
            .logout((logout) -> logout.permitAll());
        return http.build();
    }
    
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

下記が入りきらなかったコードです。
https://docs.google.com/document/d/1UJP3j2WizmekwzwpLtu94nyzeRJaSXi-6DA06L3osAE/edit?usp=sharing

自分で試したこと

LoginUserDetalisとServiceを1つでやっていたが、管理者とユーザーで分けて作成した。
.requestMatchers(HttpMethod.POST, "/user/login").permitAll()を追加したり、.userDetailsService(userLoginUserDetailsService)で指定したりした。
WebSecurityConfigを管理者とユーザーで分けたり、1つにしたりした。
Spring Securityの過去の記事を参考に、下記のサイトで書き換えたがうまくいかない状態。
https://qiita.com/suke_masa/items/908805dd45df08ba28d8

###補足情報
Java17
Eclipse2023 Full edition
Spring Boot 3.1.1
Spring Security 6

0 likes

No Answers yet.

Your answer might help someone💌