前后端分离带来的跨域问题1、什么同源策略?同源指的是 "协议 + 域名 + 端口 “ 三个相同,即使两个不同的域名指向同一个IP地址,也是非同源。同源策略是为了安全,确保一个应用中的资源只能被本应用的资源访问。否则,岂不是谁都能访问。同源http://www.domain.com/index
http://www.domain.com/module/index非同源http://www.domain.com/index
https://www.domain.com/module/indexhttp://www.domain.com/index
http://www.domainb.com/module/path1http://www.domaina.com/index
http://www.domaina.com:8081/module/path1两个相同的源之间浏览器是默认可以相互访问资源和操作DOM的。两个不同的源之间若想要相互访问资源或者操作 DOM,那么会有一套基础的安全策略的制约。具体有如下两方面的限制。1. 安全性: 浏览器要防止当前站点的私密数据不会向其他站点发送如当前站点的Cookie,LocalStorage,IndexDb 不会被发送到其他站点或被其他站点脚本读取到无法跨域获取Dom,无法发送Ajax请求。2. 可用性:大型站点的图片,音视频等资源,希望部署在独立服务器上,为缓解当前服务的压力,开放某些特定的方式,访问非同源站点如:<script><img><iframe><link><vedio>等,可以同src属性跨域访问 允许跨域提交表单/或重定向请求解决方案1.服务端解决跨域请求分两种情况a. 简单请求:请求方法使用GET/HEAD/POST请求之一仅能使用CORS安全的头部,Accept,Accept-Language, Content-Language,Content-TypeContent-Type的值只能是:text/plain,multipart/form-data,application/x-www-form- urlencoded三者其中之一服务端解决方案:在http响应头中添加 Access-Control-Allow-Origin 头,值为信任的站点。 /**
* 简单请求1
*
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "/ajaxGetReq1", method = RequestMethod.GET)
@ResponseBody
public String ajaxGetReq(HttpServletResponse response) throws IOException {
response.addHeader("Access-Control-Allow-Origin","http://localhost:8080");
return "plain text from ajax";
}
/**
* 简单请求2
*
* @param user
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "/ajaxPostReq2", method = RequestMethod.POST)
@ResponseBody
public User ajaxPostReq2(User user, HttpServletResponse response) throws IOException {
response.addHeader("Access-Control-Allow-Origin","http://localhost:8080");
return user;
}b. 复杂请求 不符合简单请求条件的即为复杂请求,访问跨域资源前,需要发起preflight预检请求(OPTIONS请求)询问何种请求是被允许的,预检请求失败,则不会发起正式的业务请求,预检请求成功,然后发起正式请求SpringBoot解决方案:1. 创建一个filter解决跨域。@Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
2.基于WebMvcConfigurerAdapter配置加入Cors的跨域import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}如果你想做到更细致也可以使用@CrossOrigin这个注解在controller类中使用。这样就可以指定该controller中所有方法都能处理来自http:19.168.1.10:8080中的请求。第一种Filter的方案也支持springmvc。第二种常用于springboot。2. 代理服务器,反向代理接口请求apache http server / nginxlocation /api {
rewrite ^/api/(.*)nbsp;/$1 break;
proxy_pass http://localhost:8081/;
}3. jsonp 方式<script>
function clickButton() {
var scriptTag = document.createElement("script");
scriptTag.src = "http://localhost:8081/jsonpReq";
document.body.appendChild(scriptTag);
}
function myFunc(myObj) {
document.getElementById("demo").innerHTML = myObj.name;
}
</script>