Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HttpSecurity多重配置未为配置的端点提供基本身份验证挑战_Java_Spring_Spring Security - Fatal编程技术网

Java HttpSecurity多重配置未为配置的端点提供基本身份验证挑战

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

我已经阅读了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]检查请求的匹配:'/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”))