SpringBoot配置Cors解决跨域问题

在研发过程中,跨域资源共享会经常碰到,使用CORS(英文全称:Cross-Origin Resource Sharing 即我们常说的跨域资源共享)可以帮助我们快速实现跨域访问,只需在服务端进行相应的授权配置,无需在前端添加额外设置,相比传统的JSONP跨域更安全和便捷。

相关术语理解
1.origin:理解为源,就是协议、域名和端口,如果请求地址的协议、域名和端口都相同则属于同源
例如:

   http://www.abc.com:80和 http://www.abc.com:80/text.html --同源
   http://www.abc.com:80和 http://www.abc.com:8080/text.html --端口号不同,不属于同源
   http://www.abc.com:80和 https://www.abc.com:80/text.html --协议不同,不属于同源
   http://www.abc.com:80和 http://www.def.com:80/ --域名不同,不属于同源

2.什么是同源策略

浏览器采用是同源策略(保证浏览器的安全),禁止浏览器加载或执行与当前网页资源来源不同的域的任何脚本

情景:
比如一个恶意网站的页面通过iframe嵌入了第三方网站的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录的时候获取第三方网站的用户名和密码。

浏览器中有哪些不受同源限制呢?
<script>、<img>、<iframe>、<link>这些包含 src 属性的标签可以加载跨域资源。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。

3.跨域
跨域是指从一个域的网页去请求另一个域的资源。比如从http://www.abc.com/ 页面去请求 http://www.def.com 的资源。

SpringBoot中的跨域授权方式

a.返回新的CorsFilter

@Configuration
public class CorsConfiger { 
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig()); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }

     private CorsConfiguration corsConfig() {

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        if(RString.isBlank(AppResource.getProperty("AllowedOrigins"))){
        	corsConfiguration.addAllowedOrigin("*");
        }else{
        	corsConfiguration.setAllowedOrigins(Arrays.asList(AppResource.getProperty("AllowedOrigins").split(",")));
        }
        
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        return corsConfiguration;
    }
}

b.重写WebMvcConfigurer
说明:spring boot2.0之后在构造spring配置文件时建议推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport ,经测试实现WebMvcConfigurer是没问题,但继承WebMvcConfigurationSupport类是会导致自动配置失效的。

@Configuration
public class CorsConfig extends WebMvcConfigurer {
 
     @Override  
        public void addCorsMappings(CorsRegistry registry) {  
            registry.addMapping("/**")  
                    .allowedOrigins("*")  
                    .allowCredentials(true)  
                    .allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")  
                    .maxAge(3600);  
        }  
}

c.使用注解(@CrossOrigin)
@CrossOrigin(origins=“http://test.com”,maxAge=3600)
参数解释:
origins:允许可访问的域列表
maxAge:准备响应前的缓存持续的最大时间(以秒为单位),默认30分钟

注解@CrossOrigin不起作用的原因
1.是springMVC的版本要在4.2或以上版本才支持@CrossOrigin
2.在Controller注解上方添加@CrossOrigin注解后,仍然出现跨域问题,解决方案之一就是,在@RequestMapping注解中没有指定Get、Post方式,具体指定后,问题解决

例如:

@RestController
@RequestMapping("/account")
public class AccountController {
      @CrossOrigin
      @GetMapping("/{id}")
      public Account retrieve(@PathVariable Long id) {
        //...
      }
 }

4.Request Headers(请求头)如下:

  Origin:表示跨域请求的原始域。
  Access-Control-Request-Method:表示跨域请求的方式。(如GET/POST)
  Access-Control-Request-Headers:表示跨域请求的请求头信息。

5.Response headers(响应头 )说明如下:

  Access-Control-Allow-Origin:表示允许哪些原始域进行跨域访问。(字符数组)
  Access-Control-Allow-Credentials:表示是否允许客户端获取用户凭据。(布尔类型)
                      使用场景:例如现在从浏览器发起跨域请求,并且要附带Cookie信息给服务器。则必须具备两个条件:
                      1. 浏览器端:发送AJAX请求前需设置通信对象XHR的withCredentials 属性为true。
                      2.服务器端:设置Access-Control-Allow-Credentials为true。两个条件缺一不可,否则即使服务器同意发送Cookie,浏览器也无法获取。

  Access-Control-Allow-Methods:表示跨域请求的方式的允许范围。(例如只授权GET/POST)
  Access-Control-Allow-Headers:表示跨域请求的头部的允许范围。
  Access-Control-Expose-Headers:表示暴露哪些头部信息,并提供给客户端。(因为基于安全考虑,如果没有设置额外的暴露,跨域的通信对象XMLHttpRequest只能获取标准的头部信息)
  Access-Control-Max-Age:表示预检请求 [Preflight Request] 的最大缓存时间。

a.例如:设置响应头(HttpServletResponse)

使用HttpServletResponse对象添加响应头(Access-Control-Allow-Origin)来授权原始域,这里Origin的值也可以设置为”*” ,表示全部放行。

    @RequestMapping("/hello")
    @ResponseBody
    public String hello(HttpServletResponse response){
        response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
        return "Hello World";
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值