Ajax跨域问题及解决
跨域问题的产生前台调用后台接口,因为前台和后台不在同一个域内产生跨越问题。
三个条件同时产生才能发生跨域问题。 解决思路从浏览器角度解决使用不检查跨域的方式启动浏览器 **chrome --disable-web-security --user-data-dir=g:temp3 不存在任何的跨域问题,可以自由访问。 此种解决方法说明,跨域是浏览器限制的行为,跟后台没有任何的关系。 针对XHR使用JSONP访问JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。 //每个测试用例的超时时间 jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; //每个请求接口的前缀 var base = "http://localhost:8080/test"; //测试模块 describe("ajax跨域测试",function () { //测试方法 it("jsonp请求",function (done) { //服务器返回结果 var result; $.ajax({ url: base + "/get1",dataType: "jsonp",success: function (json) { result = json; } }); //由于是异步请求,需要使用setTimeout来校验 setTimeout(function () { expect(result).toEqual({ "data": "get1 ok" }); //校验通过,通知jasmine框架 done(); },100); }); }); 后端增加代码 package com.fwj.ajax; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; @ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{ public JsonpAdvice(){ super("callback"); } } 使用Jsonp后端需要做改动,需要返回非Json对象。 关于Jsonp成功的原因
JSONP弊端
被调用方解决跨域 服务器端实现被调用发-Filter解决方案。【简单请求】: 【非简单请求】: 在后端增加Filter配置,在响应头中添加需要的Header。 import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CrossFilter 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; HttpServletRequest request= (HttpServletRequest) servletRequest; String origin = request.getHeader("Origin"); if(org.springframework.util.StringUtils.isEmpty(origin)){ //允许所有的远程请求 response.addHeader("Access-Control-Allow-Origin","*"); } String headers = request.getHeader("Access-Control-Request-Headers"); if(org.springframework.util.StringUtils.isEmpty(headers)) { //允许自定义头,网页可以请求各种内容类型 response.addHeader("Access-Control-Allow-Headers",headers); } //允许所有的请求方式 response.addHeader("Access-Control-Allow-Methods","*"); //允许OPTIONS预检命令缓存3600秒 response.addHeader("Access-Control-Max-Age","3600"); //使Cookie生效 response.addHeader("Access-Control-Allow-Credentials","true"); //放行 filterChain.doFilter(servletRequest,response); } @Override public void destroy() { } } 将此Filter加入Spring配置文件。 package com.fwj.ajax; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @SpringBootApplication public class AjaxApplication { public static void main(String[] args) { SpringApplication.run(AjaxApplication.class,args); } @Bean public FilterRegistrationBean registerFilter(){ FilterRegistrationBean bean =new FilterRegistrationBean(); bean.addUrlPatterns("/*"); bean.setFilter(new CrossFilter()); return bean; } } 关于OPTIONS预检命令OPTIONS它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET,POST”。 关于带Cookie类型的跨域使用Cookie时”Access-Control-Allow-Methods”,不能为 *,必须使用全匹配。 Access-Control-Allow-Credentials : true 前端代码如下 //测试方法 it("getCookie请求",function (done) { //服务器返回结果 var result; $.ajax({ type:"get",url: base + "/getCookie",xhrFields:{ withCredentials:true },100); }); NGINX配置配置原理图 server{ listen 80; server_name b.com; location/{ proxy_pass http://localhost:8080/; add_header Access-Control-Allow-Methods *; add_header Access-Control-Max-Age 3600; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Headers &http_access_control_request_headers; if ($request_method = OPTIONS){ return 3600; } } } nginx技巧: //检查nginx的配置时候正确 ./nginx -t APACHE配置略 Spring框架解决方案在需要跨域的Controller类或者需要跨域的方法上增加注解 @CrossOrigin 调用方解决跨域NGINX配置使用反向代理 server{ listen 80; server_name a.com; location/{ proxy_pass http://localhost:8081/; } location/ajaxserver{ proxy_pass http://localhost:8080/test/; } } 调用方需要访问前缀地址 “/ajaxserver” eg:http:/a.com/ajaxserver/get1 APACHE配置略 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |