由于前后端分离,导致不得不处理跨域问题.
springboot支持的跨域配置:
CorsConfig.java
package com.test.base.springCore;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 跨域请求处理
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
.maxAge(3600);
}
}
这个是能起作用的.
但由于这个配置是在spring的RequestHandler里生效的,而在这之前如果Request已经被过滤器或拦截器拒绝了,返回给前端便会导致跨域异常.
这时可以在过滤器或拦截器拒绝前手动设置跨域信息:
HttpServletResponse resp = (HttpServletResponse) response;
String origin = ((HttpServletRequest) request).getHeader("Origin");
resp.setHeader("Access-Control-Allow-Origin", origin);
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET");
resp.setHeader("Access-Control-Max-Age", "3600");
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Access-Control-Allow-Headers", "content-type");
或者不使用spring的跨域设置,将跨域配置写在自定义过滤器里:
CorsFilter.java
package com.test.base.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 处理跨域
*/
public class CorsFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(CorsFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
String origin = ((HttpServletRequest) request).getHeader("Origin");
resp.setHeader("Access-Control-Allow-Origin", origin);
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET");
resp.setHeader("Access-Control-Max-Age", "3600");
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Access-Control-Allow-Headers", "content-type");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
注册过滤器可以使用注解和过滤器配置类两种:
注解:
@Component
@WebFilter(filterName = "filterName" ,urlPatterns = "/*")
过滤器配置类:
FilterConfiger.java
package com.test.base.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 过滤器配置类,过滤器执行的先后顺序等同在此文件配置的先后顺序
*/
@Configuration
public class FilterConfiger {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LogFilter());
registration.addUrlPatterns("/*");
registration.setName("logFilter");
return registration;
}
@Bean
public FilterRegistrationBean corsFilter() {
FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CorsFilter());
registration.addUrlPatterns("/*");
registration.setName("corsFilter");
return registration;
}
@Bean
public FilterRegistrationBean loginFilter() {
FilterRegistrationBean<LoginFilter4Session> registration = new FilterRegistrationBean<>();
registration.setFilter(new LoginFilter4Session());
registration.addUrlPatterns("/*");
registration.setName("loginFilter");
return registration;
}
}
跨域的检查就是那几个响应头的配置,根据自己的需求配置即可.
另附跨域检验方法:
随便找个非https的网站,在它的console运行下面的代码,看是否报错
(function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.info(this.responseText);
}
};
xhttp.open("GET", "http://127.0.0.1:8899", true);
xhttp.withCredentials = true;
xhttp.send();
})()