一、背景
在公司空暇时间,笔者使用 AngularJS + SSM 方案编写一套权限控制系统。由于采用的是前后端分离的思想,前端页面服务启动的端口和后端服务启动端口不一致导致请求跨域问题的出现。在此,写下解决问题的流程。
二、基础知识
2.1 什么是同源
URL 由协议、域名、端口和路径组成,如果两个 URL 的协议、域名和端口相同,则表示它们同源。
2.2 什么是同源策略
浏览器的同源策略,限制了来自不同源的 document 或脚本,对当前 document 读取或设置某些属性。其目的是为了保证用户信息的安全,防止恶意的网站窃取数据。
另外,同源策略只对网页的 HTML 文档做了限制,对加载的其他静态资源如 javascript、css、图片等仍然认为属于同源。
2.3 什么是跨域
跨域,指的是浏览器不能执行其他网站的脚本。同源策略规定,AJAX 请求只能发给同源的网址,否则就报错。
建议读者先浏览文章末尾提供的参考资料进一步了解跨域相关的内容,再结合本文案例思考和理解
三、解决案例
CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。
笔者采用 CORS 方案解决问题。
3.1 前端页面设置
3.1.1 设置请求参数
在 ajax 请求参数中添加 2 个参数设置:
xhrFields: {
withCredentials:
true }
crossDomain:
true
3.1.2 源码演示
$.ajaxSetup({
dataType:
"json",
cache:
false,
xhrFields: {
withCredentials:
true },
crossDomain:
true,
complete:
function(xhr) {
if (xhr.responseJSON) {
if (xhr.responseJSON.code ==
401) {
layer.msg(xhr.responseJSON.msg);
setTimeout(
function() {
window.location.href =
"login.html";
},
1500);
}
}
else {
layer.msg(xhr.responseText);
}
}
});
3.2 后端服务器设置
3.2.1 设置跨域请求过滤器
public
class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request=(HttpServletRequest)req;
response.setHeader(
"Access-Control-Allow-Origin", request.getHeader(
"Origin"));
response.setHeader(
"Access-Control-Allow-Credentials",
"true");
response.setHeader(
"Access-Control-Allow-Methods",
"POST,GET,OPTIONS,DELETE");
response.setHeader(
"Access-Control-Allow-Headers",
"Origin,No-Cache,X-Requested-With,If-Modified-Since," +
"Pragma,Last-Modified,Cache-Control,Expires,Content-Type,X-E4M-With,userId,token");
//response.setHeader(
"Access-Control-Max-Age",
"0");
//response.setHeader(
"XDomainRequestAllowed",
"1");
chain.doFilter(req,resp);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
3.2.2 配置 web.xml 文件
<filter>
<filter-name>cors
filter-name>
<filter-class>com.light.system.web.filter.SimpleCORSFilter
filter-class>
filter>
<filter-mapping>
<filter-name>cors
filter-name>
<url-pattern>/*
url-pattern>
filter-mapping>
四、参考资料
- http://lleohao.com/2017/08/12/%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0%E8%A7%A3%E5%86%B3%E8%B7%A8%E5%9F%9F/
- http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
- http://www.ruanyifeng.com/blog/2016/04/cors.html