2016-05-30 53 views
6

我正在使用spring引導進行簡單的休息服務。爲了在Angular 2中使用它,在oauth/token端點上檢索標記時,我遇到了CORS問題。oauth /令牌上的彈簧引導休息服務選項401

Chrome中的錯誤消息如下。

error message

zone.js:101 OPTIONS http://192.168.0.9:8080/api/oauth/token 
XMLHttpRequest cannot load http://192.168.0.9:8080/api/oauth/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 401. 

相關文件如下。

MyConfig.java

@Configuration 
public class MyConfig { 
    @Bean 
    public WebMvcConfigurer corsConfigurer() { 
     return new WebMvcConfigurerAdapter() { 
      @Override 
      public void addCorsMappings(CorsRegistry registry) { 
       registry.addMapping("**") 
         .allowedOrigins("*").allowedMethods("POST, GET, HEAD, OPTIONS") 
       .allowCredentials(true) 
       .allowedHeaders("Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers") 
       .exposedHeaders("Access-Control-Allow-Origin,Access-Control-Allow-Credentials") 
       .maxAge(10); 
      } 
     }; 
    } 
} 

OAuth2ResourceServerConfig.java

@Configuration 
@EnableResourceServer 
class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter { 
    @Override 
    public void configure(HttpSecurity http) throws Exception { 
     http 
      .csrf().disable() 
      .anonymous() 
      .and() 
       .authorizeRequests() 
       .antMatchers(HttpMethod.OPTIONS,"**").permitAll() 
       .antMatchers("/authenticated/**").authenticated() 
       ; 
    } 

} 

我是新來的Java和春天。我發現了一些類似的問題,例如OAuth2 - Status 401 on OPTIONS request while retrieving TOKEN,但我真的不明白如何使它在春季啓動中工作。

請注意正常的休息控制器端點工作正常。問題是oauth/token,選項請求返回401狀態。

請在彈簧啓動時給我看一些工作代碼。謝謝!

回答

9

您可以將此CORS過濾器添加到您的項目

@Component 
@Order(Ordered.HIGHEST_PRECEDENCE) 

public class SimpleCORSFilter implements Filter { 

@Override 
public void init(FilterConfig fc) throws ServletException { 
} 

@Override 
public void doFilter(ServletRequest req, ServletResponse resp, 
     FilterChain chain) throws IOException, ServletException { 
    HttpServletResponse response = (HttpServletResponse) resp; 
    HttpServletRequest request = (HttpServletRequest) req; 
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
    response.setHeader("Access-Control-Max-Age", "3600"); 
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN"); 

    if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { 
     response.setStatus(HttpServletResponse.SC_OK); 
    } else { 
     chain.doFilter(req, resp); 
    } 

} 

@Override 
public void destroy() { 
} 

} 
+0

我在其他帖子中找到了這個答案。但在Spring Boot中,它推薦使用WebMvcConfigurerAdapter,如我的代碼所示,而不是過濾器。你可以看到他們有類似的代碼,除了「OPTIONS」部分。所以我想知道是否可以添加類似的「選項」代碼到我的文件?謝謝。 – weijun

+0

你的代碼有效! :) – weijun

+1

非常感謝你!!!!!我花了大約4天的時間解決了這個問題後,你節省了我的一天! –

1

這裏是天然的Spring框架的解決方案:

@Bean 
public CorsFilter corsFilter(CorsConfiguration config) { 
    log.debug("Registering CORS filter"); 
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
    source.registerCorsConfiguration("/api/**", config); 
    source.registerCorsConfiguration("/v2/api-docs", config); 
    source.registerCorsConfiguration("/oauth/**", config); 
    return new CorsFilter(source); 
} 
1

,如果你使用的是春天開機+春天的OAuth必須添加

@Order(Ordered.HIGHEST_PRECEDENCE) 

到您的CORS過濾器

@Configuration 
@Order(Ordered.HIGHEST_PRECEDENCE) 
public class CORSFilter implements Filter { 

    private FilterConfig config; 

    public static final String CREDENTIALS_NAME = "Access-Control-Allow-Credentials"; 
    public static final String ORIGIN_NAME = "Access-Control-Allow-Origin"; 
    public static final String METHODS_NAME = "Access-Control-Allow-Methods"; 
    public static final String HEADERS_NAME = "Access-Control-Allow-Headers"; 
    public static final String MAX_AGE_NAME = "Access-Control-Max-Age"; 

    @Override 
    public void destroy() { 

    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse resp, 
         FilterChain chain) throws IOException, ServletException { 
     HttpServletResponse response = (HttpServletResponse) resp; 
     HttpServletRequest request = (HttpServletRequest) req; 
     response.setHeader("Access-Control-Allow-Origin", "*"); 
     response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
     response.setHeader("Access-Control-Max-Age", "3600"); 
     response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN"); 

     if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { 
      response.setStatus(HttpServletResponse.SC_OK); 
     } else { 
      chain.doFilter(req, resp); 
     } 

    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     config = filterConfig; 
    } 
}