在浏览器端进行ajax请求时会出现跨域问题,如下图所示:
跨域指的是浏览器不能执行其他网站的脚本,是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
其中,同源是指域名、协议、端口均相同,只要有一个不同,那就是所谓的跨域,如:
http://www.index.com --> http://admin.index.com 这就是跨域
而非跨域:http://www.index.com --> http://www.index.com
当浏览器执行JavaScript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会执行。
跨域会阻止接口请求和dom获取和操作,浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对dom的查询。
阻止接口请求,如用ajax从一个url向另外一个端口不用的url发起请求,由于两个端口不同,属于跨域行为,浏览器会在Console会输出“No 'Access-Control-Allow-Origin' header is present on the requested resource....is therefore not allowed access.”
但是虽然浏览器禁止用户对请求返回数据的显示和操作,可浏览器确实是请求了,如果服务器没有做什么限制的话会返回数据的,在调试模式的network中可以看到返回状态为200,且可以看到返回的数据:
那么如何解决跨域问题呢?
1、跨域资源共享
CORS是一个W3C标准,称“跨域资源共享”,它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而解决ajax只能同源使用的限制。CORS需要浏览器浏览器和服务器同时支持。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。在PHP接口脚本中加入:
header('Access-Control-Allow-Origin:*');//允许所有来源访问
header('Access-Control-Allow-Method:POST,GET');//允许访问的方式
2、jsonnp实现(仅适用get请求)
$.ajax({
url: '',
type: 'GET',
dataType: 'JSONP',//重点在这里,加上这个属性就可以跨域请求了
success: function (data) {
}
});
3、后台通过过滤器开放需要访问的接口:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CrossFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(CrossFilter.class);
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
logger.debug("跨域请求进来了。。。");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletRequest.getSession();
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "*");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
httpResponse.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie");
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Content-type", "application/json");
httpResponse.setHeader("Cache-Control", "no-cache, must-revalidate");
chain.doFilter(request, httpResponse);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
在web.xml中配置过滤器和需要过滤的接口就OK啦:
<filter>
<filter-name>CrossFilter</filter-name>
<filter-class>com.hbf.filter.CrossFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CrossFilter</filter-name>
<!-- 这里配置你需要进行跨域的接口,*代表servlet当前路径下所子有路径 -->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>