Ajax跨域问题


前言

跨域在web中会常常出现,每次遇到都十分头疼,特此总结。

一、问题描述

1.什么是跨域

  • Ajax跨域问题是由浏览器的同源策略造成的, 首先要理解源这个概念.
  • 我们可以通过协议+域名+端口确定一个源. 在上面的示例中, 你可以把一个项目理解为一个源. Ajax请求可以对源内的资源发起访问, 但是不同源之间进行Ajax就会有问题.
  • 当向不同源的资源发起Ajax请求时, 浏览器会加上Origin字段来标识源
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Length: 8
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: localhost:7070
Origin: http://localhost:9090   协议+域名+端口
  • 服务器会根据Origin字段决定是否同意这次请求, 如果Origin指定的源不在许可范围内, 服务器会返回一个不带有Access-Control-Allow-Origin字段的响应. 浏览器解析时发现缺少了这个字段, 就会报错. 这种错误不能通过状态码识别, 因为状态码很有可能就是200.

2.CORS请求原理

  • 大佬的解读:跨域资源共享 CORS 详解(阮一峰)
  • 关于CORS:
    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。基本上目前所有的浏览器都实现了CORS标准,其实目前几乎所有的浏览器ajax请求都是基于CORS机制的,只不过可能平时前端开发人员并不关心而已(所以说其实现在CORS解决方案主要是考虑后台该如何实现的问题)。
  • 简化的原理图:
    在这里插入图片描述

二、问题解决

既然知道了是因为响应中缺少了 Access-Control-Allow-Origin 这个字段,因此加上即可。
1. Maven项目

  • pom.xml中添加坐标
<dependency>
	<groupId>com.thetransactioncompany</groupId>
	<artifactId>cors-filter</artifactId>
	<version>2.5</version>
    <scope>runtime</scope>
</dependency>
  • web.xml中对过滤器进行配置
    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
            <param-name>cors.allowOrigin</param-name><!--这个标签是关键, *代表所有源都能访问-->
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
        </init-param>
        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <param-value>Set-Cookie</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2. SpringBoot项目

  • 方法一:注解
    在Spring Boot 中给我们提供了一个注解 @CrossOrigin 来实现跨域,这个注解可以实现方法级别的细粒度的跨域控制。我们可以在类或者方添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。
    @RestController
	@RequestMapping("/user")
	@CrossOrigin
	public class UserController {
	   @Autowired
	    private UserService userService;

	   @RequestMapping("/findAll")
	    public Object findAll(){
	        return userService.list();
	    }
	}
  • 方法二:实现WebMvcConfigurer
    可以通过实现WebMvcConfigurer接口中的addCrosMapping()方法来实现跨域。
@Configuration
	public class WebConfig implements WebMvcConfigurer {

	    /**
	     * 跨域支持
	     * @param registry
	     */
	    @Override
	    public void addCorsMappings(CorsRegistry registry) {
	        registry.addMapping("/**")
					.allowedOrigins("*")
					.allowCredentials(true)
					.allowedMethods("GET", "POST", "DELETE", "PUT")
					.allowedHeaders(*)
					.maxAge(3600 * 24);
	    }
	}

addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。
allowedOrigins:允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:“http://www.baidu.com”,只有百度可以访问我们的跨域资源。
allowCredentials: 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以
allowedMethods:允许输入参数的请求方法访问该跨域资源服务器,如:POST、GET、PUT、OPTIONS、DELETE等。
allowedHeaders:允许所有的请求header访问,可以自定义设置任意请求头信息,如:“X-YAUTH-TOKEN”
maxAge:配置客户端缓存预检请求的响应的时间(以秒为单位)。默认设置为1800秒(30分钟)。

3. Nginx配置

location / {
	   add_header Access-Control-Allow-Origin *;
	   add_header Access-Control-Allow-Headers X-Requested-With;
	   add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

	   if ($request_method = 'OPTIONS') {
	     return 204;
	   }
	}

三、问题总结

  1. 跨域问题可以从前后端两个方面来解决。最为简便的是后端SpringBoot添加 @CrossOrigin注解;
  2. 现在比较火的axios也存在跨域问题,可以参考https://www.jianshu.com/p/8388650ff8fa

参考文章:
ajax跨域,这应该是最全的解决方案了
SpringBoot项目针对跨域问题的三种解决方案
Ajax跨域问题及解决方案
axios处理跨域问题

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值