一.什么是跨域
跨域是指 不同域名之间相互访问。跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
也就是如果在A网站中,我们希望使用Ajax来获得B网站中的特定内容
如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题。
二.什么是同一个域
同一协议,同一ip,同一端口,三同中有一不同就产生了跨域。
请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。端口不同 本机端口为80
三:前端访问服务器出现的问题:
Access to XMLHttpRequest at 'url' from origin 'null' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response
预运行响应中的访问控制允许头不允许请求头字段内容类型,也就是我们的请求head中包含了不允许的字段内容
包含自定义header字段的跨域请求,浏览器会先向服务器发送OPTIONS请求,探测该服务器是否允许自定义的跨域字段。如果允许,则继续实际的POST/GET正常请求,否则,返回标题所示错误。
解决:在系统过滤器中设置响应头信息:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//跨域请求,*代表允许全部类型
response.setHeader("Access-Control-Allow-Origin", "*");
//允许请求方式
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
//用来指定本次预检请求的有效期,单位为秒,在此期间不用发出另一条预检请求
response.setHeader("Access-Control-Max-Age", "3600");
//请求包含的字段内容,如有多个可用哪个逗号分隔如下 (如heaer中包含自定义参数,需在此项中指定)
response.setHeader("Access-Control-Allow-Headers", "content-type,x-requested-with,Authorization, x-ui-request,lang");
//访问控制允许凭据,true为允许
response.setHeader("Access-Control-Allow-Credentials", "true");
// 浏览器是会先发一次options请求,如果请求通过,则继续发送正式的post请求
// 配置options的请求返回
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpStatus.SC_OK);
response.getWriter().write("OPTIONS returns OK");
return;
}
// 传递业务请求处理
chain.doFilter(servletRequest, servletResponse);
}
解决:1.在拦截器中设置OPTIONS请求 设置成 成功!
@Slf4j
public class BlackEndInterceptor implements HandlerInterceptor {
public static final String CONTENT_TYPE_FILE = "application/json";
public static final String CONTENT_TYPE_FILE2 = "application/x-www-form-urlencoded";
private static RedisCacheService redisCacheService = getStringRedisTemplate();
/**
* 在请求处理之前进行调用(Controller方法调用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
log.info("--------------进入过滤器------------------");
long startTime = System.currentTimeMillis();
request.setAttribute("InterceptorStartTime", startTime);
if ("GET".equals(request.getMethod())) {
if (!validateGet(request, response)) {
return false;
}
return true;
}
if ("OPTIONS".equals(request.getMethod())) {
return true;
}
if (!validatePost(request, response)) {
return false;
}
return true;
}
2.在过滤器中设置响应头信息:
package com.finance.rst.map.engine.backend.web;
import com.finance.rst.map.engine.backend.service.util.RequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 解决流只能读取一次
*/
@Slf4j
@Component
public class CORSFilter implements Filter {
public CORSFilter() {
log.info("CORSFilter init");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
log.info("-----------------doFilter-------------------");
HttpServletRequest request = new RequestWrapper((HttpServletRequest)req);
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
response.setHeader("Content-Type", "application/json;charset=utf-8");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
/**
* Set Cache-Control, Pragma for IE ajax request caching disablement
* Custom item X-Session-Token for myself.
*/
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
即可!