SpringBoot+Vue-解决跨域问题

SpringBoot+Vue-解决跨域问题,第1张

所谓跨域:

在前后端分离的项目中,前台一个服务,后台一个服务。

前台的一个Axios请求打进来,要访问后台Tomcat服务器Restful接口

浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略

在默认的情况下跨域是被禁止。

IP不同或者端口号不同就是跨域

HTML5带来了CORS协议解决跨域的问题

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求。

Access-Control-Allow-Origin:http://somehost.com 表示允许http://somehost.com发起跨域请求。
Access-Control-Max-Age:86400 表示在86400秒内不需要再发送预校验请求。
Access-Control-Allow-Methods: GET,POST,PUT,DELETE 表示允许跨域请求的方法。
Access-Control-Allow-Headers: content-type 表示允许跨域请求包含content-type

 第一步:建一个前台工程放在端口号为8084上(模仿独立的前台)




    
    Page Index


COR测试

第二步:另建一个Restful接口放在端口号为8089上(模仿独立的后台)

@RestController
@RequestMapping("/ad")
public class TestController {

    @RequestMapping("/ap")
    public void run(HttpServletResponse response) {

       System.out.println("CRO SUCCESSFULLY");
    }
}

在不做任何的处理的情况下,前台的ajax调用后台8089的/ad/ap接口会发现如下情况

F12打开后会发现控制台已经报错

 其中报错信息里的这一句,正好对应了上文中的'它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制'

No 'Access-Control-Allow-Origin' header is present on the requested resource.

也就是说跨域的本质是靠Http的Header头中的Access-Control-Allow-Origin来实现跨域的。

那么也就是说如果像解决跨域问题,就必定要解决Http的Header头中的Access-Control-Allow-Origin

以下的解决方案也是我抄别人的,我这里只做研究和测试。

解决方案1:response.addHeader

在response.addHeader这个方法中加入请求发送的ip+端口号

@RestController
@RequestMapping("/ad")
public class TestController {

    @RequestMapping("/ap")
    public void run(HttpServletResponse response) {
        response.addHeader("Access-Control-Allow-Origin", "http://localhost:8084");
        System.out.println("CO SUCCESSFULLY");
    }
}

此时可以成功跨域,在打开F12此时可以发现ResponseHeaders里面Access-Control-Allow-Origin已经生效了

解决方案2:Spring框架的原生注解@CrossOrigin

@RestController
@CrossOrigin("http://localhost:8084")
@RequestMapping("/ad")
public class TestController {

    @RequestMapping("/ap")
    public void run(HttpServletResponse response) {
//        response.addHeader("Access-Control-Allow-Origin", "http://localhost:8084");
        System.out.println("CO SUCCESSFULLY");
    }
}

这种方式也同样成功

 

解决方案3: @Configration+@Bean实现自动配置重写WebMvcConfigurer

跨域的信息都封装成WebMvcConfigurer这个对象利用Spring的自动装配原理加载进去

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            //重写父类提供的跨域请求处理的接口
            public void addCorsMappings(CorsRegistry registry) {
                //添加映射路径
                registry.addMapping("/**")
                    //放行哪些原始域
                    .allowedOrigins("*")
                    //是否发送Cookie信息
                    .allowCredentials(true)
                    //放行哪些原始域(请求方式)
                    .allowedMethods("GET","POST", "PUT", "DELETE")
                    //放行哪些原始域(头部信息)
                    .allowedHeaders("*")
                    //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                    .exposedHeaders("Header1", "Header2");
            }
        };
    }
}

这种方式同样可以实现跨域

 解决方案4:放回新的CorsFilter

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送Cookie信息
        config.setAllowCredentials(true);
        //放行哪些原始域(请求方式)
        config.addAllowedMethod("*");
        //放行哪些原始域(头部信息)
        config.addAllowedHeader("*");
        //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
        config.addExposedHeader("head1");

        //2.添加映射路径
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

 这种方式同样可以实现跨域

 解决方案 1 2是可以针对单个接口进行设置

 解决方案 3 4是可以全局接口进行设置

-------------------------------------------------------------------------------------------------------------------------------

到这里还没有完.......其实我之前都是做Restful接口的,直到有人问我跨域的问题,我就像从来没关注过跨域问题一样,因为我在做Restful接口时以上四种的解决方案我从来没做过,但我的项目还是前后端分离,最后还上线了。

我也自己检讨了一下自己,问了自己两个问题

1为什么自己从来没关注过跨域问题。

2为什么我SpringBoot后端明明什么也没设置,一样实现了跨域。

结合百度和之前的代码

我总结了一下原因:不是没做跨域处理,而是没在后台做跨域处理,在VUE做的跨域处理

于是我用VUE-Cli脚手架生成了一个VUE的项目

模仿之前的工程写了一个demo.vue

  


 在Config的包下index.js下,原来是用一个代理方式来实现

查了一下代理方式的原理:将域名发送给本地的服务器(启动vue项目的服务,localhost:8080),再由本地的服务器去请求真正的服务器

module.exports = {
  dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target:"http://localhost:8089/",
        chunkOrigins: true,// 允许跨域
        pathRewrite:{
             '^/api': '' // 路径重写,使用"/api"代替target.
        }
      }
    }
}
}

测试一下,同样可以跨域成功

 在F12的时候可以看到进来的请求是

但实际请求地址为:http://localhost:8084/ad/ap,因为在vue中重写了api实际为http://localhost:8084 

这也是我为什么做的RustfulAPI时候什么也没设置,但依然实现了跨域。

当然这,这并不能成为自己认识不足的借口,学无止境,每一次的问题,就应该有一个解决办法。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/940251.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存