今天测试系统时候,浏览器控制台报错
XMLHttpRequest cannot load 'http:// …..' No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin' http://localhost:…..' is therefore not allowed access.
这是浏览器的跨域访问问题。
哪些情况会产生跨域问题
一个网站的网址组成包括协议名,子域名,主域名,端口号。比如 https://github.com/ ,其中https是协议名,www是子域名,github是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。
即使是在 http://localhost:80/ 页面请求 http://127.0.0.1:80/ 也会有跨域问题。
Web应用中前端JavaScript访问后端的REST服务默认是不能跨域的,这里的域英文中叫Origin,有时也叫Domain,包含了协议(HTTP/HTTPS),域名和端口号。不能跨域指的是,如果来自http://abc.com:80的JavaScript代码只能访问http://abc.com:80中的资源(HTTP默认端口号为80,注意端口号不同也是不同的域)。大家不妨试一试在自己的JavaScript代码中去访问Google搜索的URL,代码是不能正常运行的。
Same Origin Policy(SOP)是浏览器默认的安全模型,为什么需要SOP呢? 因为如果允许JavaScript代码访问非相同域资源的话,那么安全性将变得完全不可控。举个例子,如果另外一个网址中包含的恶意脚本就可以没有任何防备的加载进来,那就就能随意获取或者恶意修改页面元素Cookie信息等。SOP则保证了所有你访问的资源和服务是来自于你自己的服务器,外部的脚本就不能没有任何障碍得攻击你了。当然这只是基本的安全模型,通过XSS等技术,如果你的代码有漏洞的话,还是可能受到来自不同域的恶意代码的攻击,这里就不展开啦。
但是有时候我们就是希望自己的服务是可以被跨域访问的,我们知道要访问的不同域的远程资源是安全的,这时候SOP反而给我们带来了限制。这里我们使用过滤器来允许应用被跨域访问:
关键代码:
package com.yhyt.health.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CrossOriginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH,PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
在上面的例子中,设置的头信息表示允许来自任何域的客户端访问POST, GET, OPTIONS和 DELETE请求,请求的结果将缓存至多3600秒。当然,这只是一个很简单的跨域支持filter,大家可以根据需要进行更多的设置,比如只支持来自特定域的请求访问特定的资源。
在另一个系统的jsp页面请求该应用的数据:
...
<%
String contextPath = request.getContextPath();
String gateWay = (String) request.getAttribute("gateWay");
String servicePath = gateWay+"/system";
%>
...
//封装了ajax
btable.set({
openWait: true,
url: '<%=servicePath%>/dictDepartment/', //地址
paged:false,
elem: '#content', //内容容器
params: { //发送到服务端的参数
},
even: true,//隔行变色
field: 'id', //主键ID
checkbox: false,//是否显示多选框
type: 'GET'
});
...
网上有人说将dataType
设置成jsonp
也可以实现跨域访问,试了试,不知道为啥不行。
参考http://blog.youkuaiyun.com/chenyongtu110/article/details/52072823