在网上搜了很多跨域的解决方式,自己试用并做了简单的汇总,如有遗漏不足欢迎评论指出。详细原理不多做介绍,可自行百度。只简单的写下解决方式。
很多内容出自转载他人的博客,如有影响请评论指出。
相关学习连接:
Spring通过CROS协议解决跨域问题:
- https://blog.csdn.net/doecy/article/details/81202369
- https://www.cnblogs.com/owenma/p/8466856.html
Springboot中的配置: http://www.cnblogs.com/owenma/p/8466856.html
注解@CrossOrigin详解: https://blog.csdn.net/mobiusstrip/article/details/84849418#_256
在ajax中使用 jsonp来进行跨域请求,但是在HTML5之前Ajax是不允许发起跨站请求的,如果有需求的话,可以使用JSONP等方法,但是缺点就是:
- 只支持Get不支持Post;
- 本质上是脚本注入的方式,存在安全隐患;
前端页面写法:
// 回调函数
function jsonpCallback(data) {
console.log("jsonpCallback: " + data.name)
}
$("#submit").click(function() {
var data = {
name: $("#name").val(),
id: $("#id").val()
};
$.ajax({
url: 'http://localhost:3001/rest/user',
data: data,
dataType: 'jsonp',
cache: false,
timeout: 5000,
// jsonp 字段含义为服务器通过什么字段获取回调函数的名称
jsonp: 'callback',
// 声明本地回调函数的名称,jquery 默认随机生成一个函数名称
jsonpCallback: 'jsonpCallback',
success: function(data) {
console.log("ajax success callback: " + data.name)
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus + ' ' + errorThrown);
}
});
});
后台springmvc写法:
@RequestMapping("rest/user/{param}")
@ResponseBody
public Object checkStr(@PathVariable("param") String param,String callback) {
System.out.println(param+"---------------");
TaotaoResult result = userCheckService.checkUser(param);
//支持jsonp
if (!StringUtils.isEmpty(callback)) {
MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
mappingJacksonValue.setJsonpFunction(callback);
return mappingJacksonValue;
}
return result;
}
在springboot中通过cors协议解决跨域问题。
cors协议全称为Cross-Origin Resource Sharing(跨域资源共享);通过它,后端开发者可以决定资源是否能被跨域访问。关于cors协议的文章 ,可以参考 http://www.ruanyifeng.com/blog/2016/04/cors.html 这篇文章,讲的相当不错。
步骤:
用于CORS中的Http的首部有如下几个:
响应头
Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符”*”;
Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开;
Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感;
Access-Control-Expose-Headers:允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息
Access-Control-Allow-Credentials:是否允许请求带有验证信息,XMLHttpRequest请求的withCredentials标志设置为true时,认证通过,浏览器才将数据给脚本程序。
Access-Control-Max-Age:缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数;
请求头
Origin:
普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域,要与响应头中的Access-Control-Allow-Origin相匹配才能进行跨域访问;
Access-Control-Request-Method:
将要进行跨域访问的请求方法,要与响应头中的Access-Control-Allow-Methods相匹配才能进行跨域访问;
Access-Control-Request-Headers:
自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中,要与响应头中的Access-Control-Allow-Headers相匹配才能进行跨域访问
从支持跨域访问的范围说,可以有整个服务器、单个应用程序、单个接口。
a. 创建一个filter解决跨域。
package com.yanji.compute2service.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class ChangeResponseHeadFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
//"Access-Control-Allow-Origin"表明它允许" http://kbiao.me "发起跨域请求
response.setHeader("Access-Control-Allow-Origin", "*");
//"Access-Control-Allow-Methods"表明它允许GET、PUT、DELETE的外域请求
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
//"Access-Control-Max-Age"表明在3600秒内,不需要再发送预检验请求,可以缓存该结果(上面的资料上我们知道CROS协议中,一个AJAX请求被分成了第一步的OPTION预检测请求和正式请求)
response.setHeader("Access-Control-Max-Age", "3600");
//"Access-Control-Allow-Headers"表明它允许跨域请求包含content-type头当然在处理这个问题的时候前端也有不少坑,特别是Chrome浏览器不允许localhost的跨域请求,
response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
b. 基于WebMvcConfigurerAdapter配置加入Cors的跨域 全局的配置
单独进行全局配置时候需要加上头部信息
重写的方法还有
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
. exposedHeaders(“Header1”, “Header2”);
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
//重写父类提供的跨域请求处理的接口
@Override
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
.allowedOrigins("*") //允许的请求源 注意此处必须为前端地址,不能为*
.allowCredentials(true) //是否允许携带cookies
.allowedMethods("GET", "POST", "DELETE", "PUT") // 允许的http方法
.maxAge(3600); // 预请求的存活有效期
}
}
如果你想做到更细致也可以使用@CrossOrigin这个注解在controller类中使用。
springMVC的版本要在4.2或以上版本才支持@CrossOrigin
@CrossOrigin(origins = "http://192.168.1.10:8080", maxAge = 3600)
@RequestMapping("rest_index")
@RestController
public class IndexController{