跨域问题和解决方案

一. 什么是跨域

1. 同源策略

同源策略是 游览器(服务器之间的互相访问不存在跨域)
一种安全约定,为防止收到XSS、CSRF攻击,不同域之间请求资源,都算作跨域。
协议、子域名、主域名、端口号任意一个不同,即被游览器认作不同域
(即使是同一网址 IP 和域名也看做不同域,例如:127.0.0.1 和 localhost)
在这里插入图片描述

2. 同源策略限制

不受限:
(1)跳转链接、重定向、表单提交
(2)跨域资源加载(< img >、< link >、< script >、< iframe > 等),但不允许通过 JS 读写加载的内容

受限:
(1)Cookie、LocalStorage、IndexedDB 等存储性内容
(2)DOM 节点
(3)AJAX异步请求

3. 为什么有跨域限制

我们用银行页面举例

(1)DOM
黑客可以在恶意页面中用 iframe 嵌套一个银行的页面
用户在这个银行页面中输入账号密码,黑客就可以通过DOM节点获取数据

(2)CSRF攻击(跨站请求伪造)
用户的游览器中存有银行的 cookie
当用户访问恶意页面时,黑客通过 AJAX 异步请求,携带用户的银行 cookie 像银行发送请求,造成数据泄露

二、跨域解决方案

1. JSONP (已逐渐淘汰)

JSONP 利用的是游览器允许 < script > 标签跨域加载资源的机制
事先在客户端定义好回调函数
然后通过< script > 标签请求服务器,服务器返回一个执行回调函数的 JS 脚本并携带参数

优点:
使用便捷,跨平台

缺点:
只能支持 get 请求,容易受到 XSS 攻击

2. CORS(跨域资源共享)

CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,基本思想就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是否成功。

CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。

因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。

(1) 简单请求 / 非简单请求 及其预检机制

简单请求:
简单请求需同时满足两个条件

条件1:get、head、post 请求

条件2:Content-Type 的值仅限于下列三者之一:

text/plain
multipart/form-data
application/x-www-form-urlencoded

简单请求不会触发预检机制,游览器先执行请求再判断是否跨域

非简单请求:
不满足简单请求条件的均为非简单请求,例如 put、delete 请求

非简单请求在发送前,游览器会先发起一次 “预检请求”,从服务端得知是否允许该跨域,若允许再进行正常通信

(2)springboot 实现跨域

方案1: 使用 @CrossOrigin 注解(需要跨域的类或者方法上)

@CrossOrigin
@RequestMapping("/demo")
@RestController
public class DemoController {
}

方案2: 实现 WebMvcConfigurer 接口

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(1800)
                .allowedHeaders("*");
    }
}

方案3: 使用过滤器在 response 中写入响应头


@WebFilter(filterName = "CorsFilter")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "1800");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

3. WebSocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也支持跨域通信。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值