使用JAX-RS的Spring:请求'OPTIONS / login'与'POST / login不匹配

时间:2016-07-27 11:53:14

标签: java spring-security spring-boot jax-rs

我正在使用JAX-RS和Spring Boot开发REST API应用程序。我的所有资源都由JAX-RS提供。安全性由Spring安全性处理。登录和注销端点是默认的(我的api中没有定义任何登录或注销端点,我也没有接受OPTIONS定义的任何方法,正如我在一些类似的问题中看到的那样)。问题是当我尝试从网页登录(使用JavaScript)时,浏览器首先发送预检OPTIONS请求以检查功能。不幸的是,它由NotFoundExceptionMapper类提供404服务。

浏览器部分:

'(^|.*[^a-zA-Z0-9_])[.@.][[:<:]]test123[[:>:]]'

并在控制台中:

OPTIONS http://localhost:8080/xxx/login
(index):1 XMLHttpRequest cannot load http://localhost:8080/xxx/login. Response for preflight has invalid HTTP status code 404

当我使用例如Postman发布登录请求然后发送任何我的端点的OPTIONS请求时,我得到了正确的响应(这由JAX-RS处理)。

来自我的父pom.xml

o.s.security.web.FilterChainProxy        : /login at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
o.s.security.web.FilterChainProxy        : /login at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
o.s.security.web.FilterChainProxy        : /login at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
o.s.security.web.FilterChainProxy        : /login at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/logout'
o.s.security.web.FilterChainProxy        : /login at position 5 of 12 in additional filter chain; firing Filter: 'CorsFilter'
o.s.security.web.FilterChainProxy        : /login at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'OPTIONS /login' doesn't match 'POST /login
o.s.security.web.FilterChainProxy        : /login at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
o.s.security.web.FilterChainProxy        : /login at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
o.s.security.web.FilterChainProxy        : /login at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
o.s.security.web.FilterChainProxy        : /login at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
o.s.security.web.FilterChainProxy        : /login at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
o.s.security.web.FilterChainProxy        : /login at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
o.s.s.w.u.matcher.AntPathRequestMatcher  : Request '/login' matched by universal pattern '/**'
o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /login; Attributes: [permitAll]
o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5cc50bdc, returned: 1
o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
o.s.security.web.FilterChainProxy        : /login reached end of additional filter chain; proceeding with original chain
o.s.web.filter.RequestContextFilter      : Bound request context to thread: SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper@7ebf4076]
o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@4dc961c8
w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
o.s.web.filter.RequestContextFilter      : Cleared thread-bound request context: SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper@7ebf4076]
o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

WebSecurityConfig.java

<spring.version>4.3.1.RELEASE</spring.version>
<spring.security.version>4.1.1.RELEASE</spring.security.version>
<spring.boot.version>1.3.6.RELEASE</spring.boot.version>
....
<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.0.1</version>
</dependency>
...
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jersey</artifactId>
</dependency>

我的休息处理人员没有做任何特别的事情。他们只返回JSON响应而不是重定向。

CorsFilter.java

@EnableWebSecurity
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

private static final String NON_RESTRICTED_OPTS_URL = "/**";
//autowired handlers, userdetails and some static string arrays holding urls

protected void configure(HttpSecurity http) throws Exception {
    configureAuthentication(http);
    configureResourcesAccess(http);
    configureFilters(http);
    configureSession(http);
};

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(
            new BCryptPasswordEncoder());
}

private void configureAuthentication(HttpSecurity http) throws Exception {
    http.formLogin().successHandler(restAuthSuccessHandler)
            .failureHandler(restAuthFailureHandler).and().logout()
            .logoutSuccessHandler(restLogoutSuccessHandler).and()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthEntryPoint)
            .accessDeniedHandler(restAccessDeniedHandler);
}

private void configureFilters(HttpSecurity http) throws Exception {
    http.csrf()
            .disable() // temporarily disable csrf
            .addFilterBefore(new CorsFilter(),
                    UsernamePasswordAuthenticationFilter.class);
}

private void configureResourcesAccess(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, NON_RESTRICTED_OPTS_URL)
            .permitAll()
            .antMatchers(HttpMethod.POST, NON_RESTRICTED_POST_URLS)
            .permitAll()
            .antMatchers(HttpMethod.PUT, NON_RESTRICTED_PUT_URLS)
            .permitAll().anyRequest().fullyAuthenticated();
}

private void configureSession(HttpSecurity http) throws Exception {
    http.sessionManagement().sessionCreationPolicy(
            SessionCreationPolicy.IF_REQUIRED);
}
}

JerseyConfig.java

public class CorsFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response, FilterChain chain)
        throws ServletException, IOException {
    response.setHeader("Access-Control-Allow-Origin",
            request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods",
            "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers",
            "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(request, response);
}
}

我尝试通过Spring的@RequestMapping添加一个/ login方法,如某些网页上所建议的那样,添加了一个接受所有url和OPTIONS方法的方法(默认情况下我没有调度OPTIONS请求)但仍然没有运气。< / p>

0 个答案:

没有答案