Spring Security不允许我使用2个身份验证提供程序之一登录。
我的应用程序应该能够通过检查数据库中存储的信息来验证两种类型的用户-User
和Organization
。为此,我创建了两个单独的WebSecurityConfiguration
类,使用不同的SecurityFilterChain
,定义不同的表单登录,并使用2个不同的身份验证提供程序-它们使用两个不同的UserDetailsService
实现(指向不同的存储库)。
我的Organization
端点工作-注册和登录,会话成功创建,但对于User
,登录端点(/auth/login/user
)上的POST
方法被阻止-在IntelliJ上返回Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported]
作为警告,但后端在Postman上返回状态200
。应用程序没有崩溃,但POST方法没有完成-在调试时,它作为405
完成并将请求重定向到/auth/login/org
。
以下是OrgWebSecurityConfiguration
的SecurityFilterChain
:
@Bean
@CrossOrigin
public SecurityFilterChain orgSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.securityMatchers((matcher) -> matcher
.requestMatchers("/auth/*/org").anyRequest())
.authorizeHttpRequests()
.requestMatchers("/auth/register/**")
.permitAll()
.requestMatchers("/auth/login/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/login/org")
.loginProcessingUrl("/auth/login/org")
.defaultSuccessUrl("/auth/org-login-success", true)
.permitAll()
.and()
.authenticationManager(orgAuthenticationManager(http))
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/auth/login?logout")
.permitAll();
return http.build();
}
字符串UserWebSecurityConfiguration
的SecurityFilterChain
:
@Bean
@CrossOrigin
public SecurityFilterChain userSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.securityMatchers((matcher) -> matcher
.requestMatchers("/auth/*/user").anyRequest())
.authorizeHttpRequests()
.requestMatchers("/auth/register/**")
.permitAll()
.requestMatchers("/auth/login/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/login/user")
.loginProcessingUrl("/auth/login/user")
.defaultSuccessUrl("/auth/login-success", true)
.permitAll()
.and()
.authenticationManager(userAuthenticationManager(http))
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/auth/login?logout")
.permitAll();
return http.build();
}
型userAuthProvider
:
@Bean
public DaoAuthenticationProvider userAuthProvider() {
DaoAuthenticationProvider userAuthenticationProvider = new DaoAuthenticationProvider();
userAuthenticationProvider.setUserDetailsService(userDetailsService);
userAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return userAuthenticationProvider;
}
型orgAuthProvider
:
@Bean
public DaoAuthenticationProvider orgAuthProvider() {
DaoAuthenticationProvider orgAuthenticationProvider = new DaoAuthenticationProvider();
orgAuthenticationProvider.setUserDetailsService(organizationDetailsService);
orgAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return orgAuthenticationProvider;
}
型orgAuthenticationManager
和userAuthenticationManager
都是通过定义DaoAuthenticationProvider
类型的身份验证提供程序并为每个提供程序设置适当的UserDetailsService
来创建的,并在AuthenticationManagerBuilder
上实现所创建的身份验证提供程序。在本例中,User
的身份验证管理器被设置为主身份验证管理器,使用@Primary
注解。
我尝试按照this question在UserWebSecurityConfiguration
上使用@Order(0)
注解,但问题仍然存在。我还禁用了csrf。
1条答案
按热度按时间v6ylcynt1#
我通过将两个SecurityFilterChains合并为一个来解决这个问题,并将
AuthenticationProvider
s添加到userAuthenticationManager
中,如下所示:字符串
然后通常将
userAuthenticationManager
添加到securityFilterChain
(之前的userSecurityFilterChain
):型
现在,我只使用一个表单登录来验证
User
和Organization
-/auth/login
。解释:
通过在
application.properties
上添加trace=true
,我能够确定对/auth/login/user
的POST
请求返回状态405
,并被重定向为对/auth/login/org
的GET
请求。这意味着orgSecurityFilterChain
被认为是应用程序上的“默认”过滤器,即使userSecurityFilterChain
被标记为Order(0)
。它允许访问/auth/*/user
,但发生的情况是,即使我访问了用户端点(应该使用userSecurityFilterChain
),仍然使用了orgSecurityFilterChain
,因为它是默认的过滤器,它将/auth/login/org
Map为表单登录名。这意味着,即使该请求应该由userSecurityFilterChain
处理(它将登录端点Map为/auth/login/user
),它也由orgSecurityFilterChain
处理,而orgSecurityFilterChain
不支持POST
对/auth/login/user
的请求。