跨域问题
打开浏览器检查页面会发现没有输出服务器返回的消息而是,出现了一个错误信息,这就是前后端分离最常见的跨域问题
问题原因
这是因为浏览器都采用了同源策略,即不允许访问不属于本服务器的资源。
同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,浏览器会先发送OPTION请求进行预检查,判断服务器是否允许跨域,如果允许才发送真正的请求,否则抛出异常。
简单的说:
同源策略是浏览器的核心安全机制,其不允许在页面中解析执行来自其他服务器数据
同源限制
1、不允许访问非同源网页的Cookie、LocalStorage 和 IndexedDB。
2、不允许向非同源地址发送ajax请求。
如何判断跨域
当请求的url的协议,域名,端口号三者中任意一个与当前url不同,即为跨域
什么时候会产生跨域问题
当浏览器在解析数据时,页面中js代码请求了非同源的资源,则会产生跨域问题,当浏览器直接跳转到另一个非同源页面,不会发生跨域问题
跨域解决方法
需要设置浏览器允许解析跨域请求的数据,但是这个设置必须放在服务器端,由服务器端来判断对方是否可信任
设置接口:
在需要访问的接口的响应头中添加一个字段,告诉浏览器,某个服务器是可信的
response.setHeader("Access-Control-Allow-Origin","*");
其值可以是某个或多个指定的域名,也可以是*表示信任所有地址
//指定允许其他域名访问
'Access-Control-Allow-Origin:http://XXX.XXX.XXX'//一般用法(*,指定域,动态设置),注意*不允许携带认证头和cookies
//预检查间隔时间
'Access-Control-Max-Age: 1800'
//允许的请求类型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//列出必须携带的字段
'Access-Control-Allow-Headers:x-requested-with,content-type'
过滤器设置
通过过滤器进行整体设计:
@WebFilter(filterName = "HTTPFilter",urlPatterns = "/*")
public class HTTPFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse)resp;
//允许访问的方法:POST,GET
response.setHeader("Access-Control-Allow-Methods","POST,GET");
//设置响应类型为json数据
response.setContentType("application/json;charset=utf-8");
//允许http://127.0.0.1:8848跨域访问,写死了一般不这样写
//response.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8848");
//动态设置
ArrayList<String> hosts = new ArrayList<String>();
hosts.add("http://127.0.0.1:8848");
HttpServletRequest request = (HttpServletRequest)req;
if (hosts.contains((request.getHeader("Origin")))){
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
}
chain.doFilter(req, resp);
}
}
cookie跨域
默认情况下cookie是不允许跨域传输的.可以通过以下方式来解决
第一步
浏览器端设置允许cookie跨域
第二步
服务器端在响应中添加字段,说明允许cookie跨域
该值只能是true,为false无效,默认为false
#'Access-Control-Allow-Credentials:true'
跨域问题的解决方案补充
跨域问题除了通过设置header的方式来允许浏览器进行跨域访问外,也可以通过反向代理来解决跨域问题
代理服务器
当我们使用了代理后,可以利用代理服务器来完成请求转发,即所有请求,都会先发送到代理服务器,代理服务器再和真正的服务器进行交互,而这个交互过程是不会产生有跨域问题产生的
ngin 和node.js等都可以作为代理服务器
在开发阶段通常是使用node+vue来完成环境搭建 上线则使用nginx
强调
因为跨域问题是因为同源策略,而同源策略只是针对浏览器的一个策略,即在使用除浏览器之外的其他任何客户端请求都不会产生跨域问题