目录
- 什么是跨域?
- 如何解决跨域问题?
- JSONP (JSON with Padding)
- CORS(跨源资源共享)
- @CrossOrigin注解实现
- WebMvcConfigurer addCorsMappings
- CorsFilter
- 代理服务器反向代理(推荐)
什么是跨域?
跨域是指浏览器为了安全性,设定的一种同源策略。只有当协议、域名和端口都相同的时候,两个页面之间才能相互访问对方的 DOM、Cookie 等数据。如果不满足这些条件,那么数据访问就会被浏览器阻止,我们称之为跨域。这是一种安全机制,防止用户的信息被恶意的网站获取。但是在实际开发中,我们经常需要进行跨域请求,比如使用 ajax 请求其他网站的 API,这时候就会遇到跨域问题。
域名不同,协议不同,端口不同,二级域名不同,ip不同都算作跨域。
要注意的是,跨域异常只会在前端发生,就是因为浏览器的同源策略。在后端通过restTemplate或者通过HttpClient去请求其他的域,此时虽然是跨域但是不会出现异常。
如何解决跨域问题?
JSONP (JSON with Padding)
JSONP是一种比较老的方法,目前已经慢慢被替代。它通过动态插入一个<script>标签到HTML中来获取跨域数据。
优点是它足够老所以在浏览器上的兼容性很好。
缺点是它只能用于GET请求,并且需要在前后端都写上相应的代码来支持,并且不安全,容易受到 XSS 攻击(利用漏洞向网页中注入恶意的客户端脚本)。
比如下面在前端通过Ajax的方式进行跨域请求,需要指定数据类型为jsonp,这样就会自动在请求参数中加入一个叫Callback的参数默认随机,作为一个秘钥传到后端,后端还会返回回来相当于一次握手,表示合法跨域请求,便可以进行跨域访问了。
后端在springboot实现也很简单,只需要声明一个Callback的参数来接收,然后返回JSONObject的对象,将Callback作为第一个参数,第二个参数是返回给前端的json数据data。比如假设这里传入的Callback是xushu,返回的数据格式就是xushu(data)
CORS(跨源资源共享)
CORS是一种W3C规范,它允许在服务器端设置哪些源可以访问服务器的资源。这是通过服务器发送特殊的HTTP头来实现的。
优点是只需要修改后端的代码,前端不需要干预,所以没有jsonp的耦合缺点,浏览器一旦发现请求跨源,就会自动添加一些附加的头信息,但用户察觉不到。
缺点是需要浏览器支持,比如ie就不能低于10版本。
在springboot中实现CORS有三种方式:
@CrossOrigin注解实现
可以设置当前的这一个接口支持跨域请求,并且还可以在注解属性里设置跨域来源,只有这个来源才支持跨域请求。
WebMvcConfigurer addCorsMappings
配置一个实现了WebMvcConfigurer的Bean,重写addCorsMappings方法,通过方法参数里的注册器来批量添加哪些接口允许跨域请求。
CorsFilter
如果想配置所有的接口都支持跨域,就可以通过配置一个过滤器的Bean,通过这个Bean就可以去限制所有的接口是支持跨域的、
代理服务器反向代理(推荐)
比如通过nginx,不需要在前后端做任何配置,只需要在nginx进行配置,此时浏览器请求的是同一个域,但浏览器检测不到你进行了跨域,因为我们是在nginx这一层转到我们的后端,但是后端跟后端之间是不存在跨域的,这便解决了前端的跨域异常。
这种方法的优点是不需要修改任何前后端代码,同时它可以隐藏你的真实服务器地址,增加安全性。
缺点是它可能需要额外的服务器资源。