关于Ajax跨域的解决方案

本文深入解析了Ajax跨域的问题,包括其产生的原因、常见的解决方案,如通过修改浏览器设置、使用jsonp、服务器端处理及Nginx配置等方法,并详细介绍了在SpringBoot项目中如何通过Filter和注解解决跨域问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于Ajax跨域的解决方案和一些个人理解

Ajax跨域的原因

  • 浏览器限制
  • 跨域(协议、主机名、端口有一个不同就会产生跨域)
  • xhr请求(XMLHttpRequest)
    当以上三个条件同时满足时才会产生ajax跨域

Ajax跨域的解决方案

只要破坏上述三个条件之一就可以解决跨域问题

  • 浏览器的启动参数上来设置,使浏览器不做跨域校验(不常用)
    以谷歌浏览器为例,在chrome.exe所在的路径按下shift键,点击右键,点击“在此处打开命令行窗口”,然后输入chrome --disable-web-security就可以了,此方法不常用,因为需要在客户端操作,而大多数用户是不会操作的

  • xhr解决==》jsonp(不常用)
    以下是谷歌浏览器中如何查看是否xhr请求(按F12,然后在弹出框中点击NetWork的All)
    在这里插入图片描述
    使用jsonp来传输,jsonp会把动态创建script标签来进行请求,而对于服务器后台返回的数据用scprit标签形式进行解析(此时后台必须进行改动返回jsonp数据,否则前台会解析异常

    js代码:

    $.ajax({
        url: "http://localhost:8080/ajaxTest",
        dataType: "jsonp",
        jsonp: "callback",		// 此处的字段应和后台统一,否则不会返回jsonp格式
        success: function (json) {
            alert(json)
        }
     })
    

    后台接口:

    @RequestMapping(value = "/ajaxTest")
    public Result ajaxTest(){
        System.out.println("ajaxtest方法被调用了");
        return ResultUtil.success();
    }
    

    浏览器控制台:

    Uncaught SyntaxError: Unexpected token(这里是解析异常)
    

    服务器给出的json数据依旧能拿到,但控制台会报出解析异常,因为Jsonp解析的是script字段,此时应对后台接口进行改动(此处改动是基于springboot的):

    import org.springframework.web.bind.annotation.ControllerAdvice;  
    import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;  
      
    @ControllerAdvice
    // AbstractJsonpResponseBodyAdvice在Springboot 2.x已废弃
    public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{  
      
        public JsonpAdvice() {  
            super("callback");  		// 	此处字段和上边Ajax的jsonp应统一
        }  
    }
    

    jsonp的弊端:

    1. 服务器代码需要改动(自己的项目可以改,如果是别人的项目那就。。。)
    2. 只能支持get请求(请求和返回的都是script代码)
    3. 不是xhr请求
  • 跨域方面解决(常用)
    对于跨域的请求,浏览器会在请求头上加上Origin,而在服务器返回数据时判断响应头有无跨域信息,若没有则会报错
    在这里插入图片描述
    被调用方解决跨域:

    1. 服务器端实现
      使用Filter来进行处理
		// 注册filter
	    @Bean
	    public FilterRegistrationBean registerFilter(){
	        FilterRegistrationBean bean = new FilterRegistrationBean();
	        // 设置所有请求都经过过滤器
	        bean.addUrlPatterns("/*");
	        // 设置添加的过滤器
	        bean.setFilter(new CrosFilter());
	        return bean;
	    }
		public class CrosFilter implements Filter {
		    @Override
		    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		        HttpServletResponse response = (HttpServletResponse)servletResponse;
		        // 设定允许请求的域
		        response.addHeader("Access-Control-Allow-Origin","*");
		        // 设定允许请求的头(简单请求不需要加,非简单请求需要带上)
		        response.addHeader("Access-Control-Allow-Headers","*");
		        // 设定允许请求的方法
		        response.addHeader("Access-Control-Allow-Methods","*");
		    }
		
		    @Override
		    public void init(FilterConfig filterConfig) throws ServletException {
		
		    }
		
		    @Override
		    public void destroy() {
		
		    }
		}

带cookie的跨域filter设置(对于带自定义请求头的跨域,只许要在过滤器返回中添加对应请求头)

public class CrosFilter implements Filter {
    @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(!StringUtils.isEmpty(origin)){
            // 设定允许请求的域
            response.addHeader("Access-Control-Allow-Origin",origin);
        }
        // 设定允许请求的头
        response.addHeader("Access-Control-Allow-Headers","Content-Type");
        // 设定允许请求的方法
        response.addHeader("Access-Control-Allow-Methods","*");
        response.addHeader("Access-Control-Max-Age","3600");

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}
  1. Nginx配置
    待添加—
  2. Apache配置
    待添加----
  3. spring框架的跨域注解
    @CrossOrgin
    可以加在类或方法上来解决跨域

调用方解决
Nginx反向代理
Apache方向代理

参考: https://www.imooc.com/learn/947

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值