Spring security - 指定顺序时多个httpsecurity不起作用[重复]
Posted
技术标签:
【中文标题】Spring security - 指定顺序时多个httpsecurity不起作用[重复]【英文标题】:Spring security - multiple httpsecurity not work when specify order [duplicate] 【发布时间】:2020-01-04 16:55:46 【问题描述】:我已按照以下说明为管理员和用户创建了两个不同的 http 安全块。 docs.spring.io/spring-security-multiple-httpsecurity
如文档所述,如果 URL 不以 /aaa 开头,则将使用另一个配置进行模式。
但是当我将 @Order(1) 放在管理块时,管理页面工作正常,用户页面不会重定向到登录页面 /login/user
当我将 @Order(1) 放在用户块时,用户页面工作正常,管理页面也不会重定向到登录页面 /login/admin。
这是我的java代码
@EnableWebSecurity
public class MultiHttpSecurityConfig
/**
* intercept user url
*/
@Configuration
@Order(1)
public static class UserWebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
CustomAuthenticationSuccessHandler successHandler;
@Autowired
CustomAuthenticationFailureHandler failureHandler;
@Autowired
private CustomAuthenticationProvider customAuthProvider;
@Autowired
private CustomUserDetailsService userDetailsService;
@Value("$my.cookie.timeout")
private int cookieTimeOut;
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**, /fonts/**").permitAll()
.antMatchers("/bbb/**","/aaaa/**").hasAnyRole("USER");
http.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler)
.loginPage("/login/user").permitAll();
http.logout().permitAll();
http.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(cookieTimeOut);
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(customAuthProvider);
auth.userDetailsService(userDetailsService);
/**
* intercept admin url
*/
@Configuration
public static class AdminWebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
CustomAuthenticationSuccessHandler successHandler;
@Autowired
CustomAuthenticationFailureHandler failureHandler;
@Value("$my.cookie.timeout")
private int cookieTimeOut;
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**, /fonts/**").permitAll()
.antMatchers("/ccc/**","/dddd").hasAnyRole("ADMIN");
http.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler)
.loginPage("/login/admin").permitAll();
http.logout().permitAll();
http.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(cookieTimeOut);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication()
.withUser("test").password("test").roles("ADMIN");
更新:
如下 dur 所说,关键原因是 authorizeRequests() 方法匹配 Order(1) 中的所有 url,所以我需要添加 antMatcher("/bbb/* >")** 首先在 authorizeRequests() 之前。
但 antMatcher() 只匹配一种 url ,如果我还有一种 url 要匹配,例如 "/bbb/" , "/aaa/*" ,如何实现这 ? 然后我需要再添加一个 WebSecurityConfigurerAdapter 配置? 有没有更好的方法来减少代码?
我在 spring-security SDK requestMatchers() 方法中找到了解决方案,它在 requestMatchers() 方法上方提供了一个示例。
下面是我在 Order(1) 处匹配用户网址的代码
http.csrf().disable();
http.requestMatchers()
.antMatchers("/bbb/**", "/aaa/**")
.and()
.authorizeRequests()
.antMatchers("/**").hasAnyRole("USER");
http.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler)
.loginPage("/login/user").permitAll();
http.logout().permitAll();
那么bbb和aaa都已经匹配好了,不需要再创建配置
但是又出现了一个问题,当将用户名和密码发布到登录/用户界面时会显示“405 method not allowed”登录页面,而管理页面工作正常
我搜索了谷歌,它告诉我要禁用 csrf,但我已经禁用 csrf...
【问题讨论】:
两种配置都适用于/**
(任何请求),所以使用第一个。如果您添加订单,则使用订单最低的订单。
【参考方案1】:
在我的一个项目中,我没有使用表单登录,而是实现了一个自定义 AccessDeniedHandler 和 AuthenticationEntryPoint,它可以使用我需要的一些自定义逻辑重定向到不同的登录页面。但是,loginPage() 最终也是一个 AuthenticationEntryPoint。
它们可以通过以下方式添加:
.exceptionHandling().authenticationEntryPoint(new YourCustomAuthEntryHandler()).and()
.exceptionHandling().accessDeniedHandler(new YourCustomAccessDeniedHandler())
这只是一个想法,也许值得检查一下。
此外,我认为您需要对所有请求进行身份验证,请在 authorizeRequests() 块中为两个配置添加此行:
.anyRequest().authenticated()
【讨论】:
现在想想,你实际上可以有一个安全配置:在 auth 入口处理程序中检查请求 url 如果有来自管理站点,你可以将它重定向到管理员登录,但它不是最好的解决方案,但应该可以。 非常感谢您的回复,我会考虑使用它:)以上是关于Spring security - 指定顺序时多个httpsecurity不起作用[重复]的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Security Java Config 中创建多个 HTTP 部分