前后端分离带来的跨域问题

1、什么同源策略?
同源指的是 "协议 + 域名 + 端口 “ 三个相同,即使两个不同的域名指向同一个IP地址,也是非同源。
同源策略是为了安全,确保一个应用中的资源只能被本应用的资源访问。否则,岂不是谁都能访问。
同源
http://www.domain.com/index http://www.domain.com/module/index
非同源
http://www.domain.com/index https://www.domain.com/module/index
http://www.domain.com/index http://www.domainb.com/module/path1
http://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 / nginx
location /api { rewrite ^/api/(.*)$ /$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>


还没有评论,来说两句吧...