Java HttpSecurity多重配置未为配置的端点提供基本身份验证挑战
我已经阅读了Spring文档,看到了一个关于多HTTP配置的相关SO问题,但似乎我遗漏了一些东西 当我尝试转到Java HttpSecurity多重配置未为配置的端点提供基本身份验证挑战,java,spring,spring-security,Java,Spring,Spring Security,我已经阅读了Spring文档,看到了一个关于多HTTP配置的相关SO问题,但似乎我遗漏了一些东西 当我尝试转到/api/endpoint/时,我收到403错误,即使我希望收到一个基本的http身份验证挑战 @EnableWebSecurity public class MultiHttpSecurityConfig { @Autowired private DataSource dataSource; @Autowired public void config
/api/endpoint/
时,我收到403错误,即使我希望收到一个基本的http身份验证挑战
@EnableWebSecurity
public class MultiHttpSecurityConfig {
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username,password, is_active from user where username=?")
.authoritiesByUsernameQuery("select username, role from user_roles where username=?")
.passwordEncoder(passwordEncoder());
}
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/endpoint")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
@Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").access("hasRole('ROLE_USER')")
.antMatchers("/customer/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')")
.antMatchers("/buy/**").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login-error")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling()
.accessDeniedPage("/error-403")
.and()
.csrf();
}
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
应用程序初始化为:
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ServiceConfig.class, PersistenceConfiguration.class, MultiHttpSecurityConfig.class,
MailConfig.class, MvcConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
container.addListener(new ApplicationCycleControlleristener());
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(MvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher",
new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(TMP_FOLDER,
MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
dispatcher.setMultipartConfig(multipartConfigElement);
}
正如文件所说,我预计第一个问题将引发挑战,但事实似乎并非如此
这就是spring调试所显示的内容
[AntPathRequestMatcher.java:157]检查请求的匹配:'/api/endpoint';针对“/api/endpoint”
[FilterChainProxy.java:325]/api/endpoint位于附加过滤器链中12个位置中的第1个位置;正在启动筛选器:“WebAsyncManagerIntegrationFilter”
[FilterChainProxy.java:325]/api/端点位于附加过滤器链中12个位置中的第2个位置;正在启动筛选器:“SecurityContextPersistenceFilter”
[HttpSessionSecurityContextRepository.java:174]当前不存在HttpSession
[HttpSessionSecurityContextRepository.java:116]HttpSession中没有可用的SecurityContext:null。将创建一个新的。
[FilterChainProxy.java:325]/api/端点位于附加过滤器链中12个位置中的第3个位置;触发过滤器:“HeaderWriterFilter”
[HstsHeaderWriter.java:130]未注入HSTS标头,因为它与requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter不匹配$SecureRequestMatcher@33a327e2
[FilterChainProxy.java:325]/api/endpoint位于附加过滤器链中12个位置中的第4个位置;正在启动筛选器:“CsrfFilter”
[CsrfFilter.java:110]为找到无效的CSRF令牌http://localhost:8080/app/api/endpoint
[HttpSessionSecurityContextRepository.java:352]SecurityContext为空或内容为匿名-上下文将不会存储在HttpSession中。
[SecurityContextPersistenceFilter.java:119]请求处理完成后,SecurityContextHolder现在已清除
[DispatcherServlet.java:865]名为“dispatcher”的DispatcherServlet正在处理[/app/error-403]的POST请求
[AbstractHandlerMethodMapping.java:310]查找路径的处理程序方法/error-403
供将来参考,以供有相同问题的人参考
Spring Security似乎默认启用了csrf,您需要在HttpSecurity
configure
方法中手动禁用它。我发现按预期工作的唯一方法如下:
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
// Build the request matcher for CSFR protection
RequestMatcher csrfRequestMatcher = new RequestMatcher() {
// Disable CSFR protection on the following urls:
private AntPathRequestMatcher[] requestMatchers = { new AntPathRequestMatcher("/api/endpoint") };
@Override
public boolean matches(HttpServletRequest request) {
if (request.getMethod().matches("^GET$"))
return false;
for (AntPathRequestMatcher rm : requestMatchers) {
if (rm.matches(request)) {
return false;
}
}
return true;
} // method matches
};
http.antMatcher("/api/endpoint").authorizeRequests().anyRequest().hasRole("ADMIN").and().httpBasic().and()
.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);
}
}
从那以后,一切似乎都如我所希望的那样顺利。最好也在文档中。如果我没有注意到,请让我知道并更新答案。那么我是否应该为“api/端点”禁用CSRF?但是我想为其他端点保留它。是否使用/api/endpoint的POST?是的。发送json后。是否要为非
GET
和/api/endpoint
的所有请求启用CSRF,然后可以在配置中编写requireCsrfProtectionMatcher(新的NegatedRequestMatcher(新的AntPathRequestMatcher(“/api/endpoint”,“GET”))
。