我已阅读Spring文档,并看到了多个HTTP配置的相关SO问题,但似乎我遗漏了一些东西。
当我尝试转到/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] Checking match of request : '/api/endpoint'; against '/api/endpoint'
[FilterChainProxy.java:325] /api/endpoint at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
[FilterChainProxy.java:325] /api/endpoint at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
[HttpSessionSecurityContextRepository.java:174] No HttpSession currently exists
[HttpSessionSecurityContextRepository.java:116] No SecurityContext was available from the HttpSession: null. A new one will be created.
[FilterChainProxy.java:325] /api/endpoint at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
[HstsHeaderWriter.java:130] Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@33a327e2
[FilterChainProxy.java:325] /api/endpoint at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
[CsrfFilter.java:110] Invalid CSRF token found for http://localhost:8080/app/api/endpoint
[HttpSessionSecurityContextRepository.java:352] SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
[SecurityContextPersistenceFilter.java:119] SecurityContextHolder now cleared, as request processing completed
[DispatcherServlet.java:865] DispatcherServlet with name 'dispatcher' processing POST request for [/app/error-403]
[AbstractHandlerMethodMapping.java:310] Looking up handler method for path /error-403
答案 0 :(得分:0)
以后参考具有相同问题的人。
似乎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);
}
}
之后,一切似乎按照我的希望运作。在文档中也是好的。如果是,我没有注意到,请告诉我,并将更新答案。