[英]CORS error connecting Angular to Spring (localhost 8080 <--> localhost 4200)
[英]How to enable CORS between Spring and Angular 2 on localhost
我在 Spring 版本 4.3.4.RELEASE 和 Spring 安全版本 4.2.2.RELEASE 上有一個帶有 Java 后端的舊項目。 沒有辦法更新庫,我必須使用現有的庫。 該項目不是 REST API,沒有 RestController 和 WebMvcConfigurer。 所以,我按照這里的建議配置了 cors :
@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
protected SecurityConfiguration() {
super();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// allow anonymous resource requests
.antMatchers(HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers(HttpMethod.POST, "/rpc/*").permitAll()
.anyRequest().permitAll();
httpSecurity.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
// disable page caching
httpSecurity.headers().cacheControl();
}
}
Cors 過濾器:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter extends OncePerRequestFilter {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CorsFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.error("CORS filter: " + request.getMethod());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, xsrf-token");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
在 web.xml 中所有 context-param 之后和 listeners 之前(這是應用程序中唯一的過濾器):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>web.servlet.response.CorsFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我在 localhost:8080 上運行后端,在 localhost:8081 上運行前端但是,當我嘗試發送帶有 application/json 的 POST 請求時,瀏覽器控制台中出現錯誤
Access to XMLHttpRequest at 'http://localhost:8080/rpc' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
另外,我希望在后端看到日志“CORS filter: POST”,我把它放在那里檢查它是否會進入過濾器,但沒有這樣的日志。
請,關於為什么它不起作用的任何建議? 我需要在請求中堅持使用 application/json,並且有時在應用程序中還有一個 Authorization 標頭,因此無法完全避免 cors。 這可能是 Angular 2 的問題嗎?
我不熟悉 spring 或 java,但我想我明白這個問題。
我假設您的日志過濾器不起作用,因為 spring 框架在您的過濾器被執行之前短路了該請求。
這里的問題可能出在配置中的某個地方,但我認為解決給定問題的方法通常是不正確的。
CORS 是出於某些目的而創建的,通過允許來自所有其他來源的瀏覽器的請求,您實際上會產生一些潛在的安全問題。
理想情況下,如果:服務器和客戶端都是您的應用程序,則從客戶端,您應該僅向托管客戶端應用程序的同一來源發出請求。 因此,在您本地的情況下,它應該向localhost:8081
發出請求,您可以通過在發出請求時省略客戶端的主機基地址來做到這一點。
為了讓它工作,對於開發環境,最好的選擇是為 angular 設置代理(代理從localhost:8081
到localhost:8080
請求),詳細的設置信息在這里。
對於生產環境,您需要在同一來源上托管后端服務器/客戶端應用程序。 您可以通過在后端服務器/客戶端 Web 服務器前面設置一些代理服務器,或直接在后端服務器上托管客戶端應用程序(角度靜態輸出文件)來實現。
另一種選擇是做您嘗試做的事情,但不允許來自所有來源的請求(不是.permitAll()
),而是 - 列出特定的允許來源(如localhost:8081
)。 但這並不是那么干凈,而且您還需要為開發環境和生產指定不同的來源。
這個錯誤是拒絕OPTION web方法導致的,所以應該在configure方法中添加如下語句:
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
像這樣:
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// allow anonymous resource requests
.antMatchers(HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.POST, "/rpc/*").permitAll()
.anyRequest().permitAll();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.