问题总结
- 一般来讲,后端用下面三个方式来解决跨域问题。
一般来用过滤的方式来解决。 - 配置跨域配置后如果还是报错的话,不要急着怀疑跨域配置是否生效。
- 看下该接口是否调通
- 看下过滤器是否执行(配置中添加log打印看是否打印)
- 打断点,查看原因
- 跨域问题是浏览器发出请求后,返回的信息被拦截了,额如实请求发不出去。
- 跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。理解这一点是很重要的。
- 报跨域问题不一定是跨域问题,也可能是接口调不通,还可能是接口调通但是返回值被Return掉了,(不是异常)。因此调通了,但是就是跨域异常。
问题解决
问题一
Access to XMLHttpRequest at ‘http://portal.yunjiglobal.com/authority_system/permission/getMenuByworkCodeAndSyst
emId’ from origin ‘http://attendance.yunjiglobal.com’
has been blocked by CORS policy: Request header field contenttype is not allowed by
Access-Control-Allow-Headers in preflight response.
上面中看起来是跨域的问题,报这个错是因为,返回值没有拿到,因此报跨域。但是在代码中发现是因为,这个接口在进行SSO登陆验证中没有传入Cookie,导致该接口没有通过SSO验证,直接被Return掉了,因此没有返回值,因此浏览器拿不到返回值,因此报这个错。
问题二
这个错误是报503,也是跨域的报错。仔细检查发现是重新部署后,项目的端口号改变,也是导致接口调不通,报这个错。
注解跨域
- springMVC的框架在4.2以上的版本就可以使用注解来实现跨域,在controller的文件上添加@Cross Origin(origins="*")支持所有的跨域
过滤跨域
- 代码
@Slf4j
//@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
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,x-token,ticket,Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Host,Origin,User-Agent");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Headers", "Content-Type,x-token,ticket,Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Host,Origin,User-Agent");
//response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Expose-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
log.info("*********************************过滤器被使用**************************");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
- 拦截器实现了之后就需要在web.xml中配置,使拦截器发挥效果
<filter>
<filter-name>cors</filter-name>
<filter-class>xxx.xxxx.HeadersCORSFilter</filter-class><!--过滤器路径-->
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/url/*</url-pattern><!--接口前缀-->
</filter-mapping>
这个web配置,需要测试下。
CorsConfig 配置
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 允许任何头
corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等)
corsConfiguration.setAllowCredentials(true); //是否支持安全证书
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
CorsConfigration 配置
//@Configuration
@Slf4j
public class CorsConfigration implements WebMvcConfigurer{
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(request.getHeader("origin"))
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("Content-Type,x-token,ticket,Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Host,Origin,User-Agent");
log.info("CorsConfigration配置执行11");
}
}