前后端分离项目跨域问题的解决方案

Spring Boot 中处理跨域有三种方式,@CrossOrigin 注解、WebMvcConfigurer.addCorsMappings 以及 CorsFilter。前两种本质上通过 CorsInterceptor 触发调用,后者是一个普通的 Filter。

1.CORS 是什么
首先我们要明确,CORS 是什么,以及规范是如何要求的。

CORS 全称是 Cross-Origin Resource Sharing,直译过来就是跨域资源共享。要理解这个概念就需要知道域、资源和同源策略这三个概念。

        域,指的是一个站点,由 protocal、host 和 port 三部分组成,其中 host 可以是域名,也可以是 ip ;port 如果没有指明,则是使用 protocal 的默认端口.
        资源,是指一个 URL 对应的内容,可以是一张图片、一种字体、一段 HTML 代码、一份 JSON 数据等等任何形式的任何内容。
        同源策略,指的是为了防止 XSS,浏览器、客户端应该仅请求与当前页面来自同一个域的资源,请求其他域的资源需要通过验证。
了解了这三个概念,我们就能理解为什么有 CORS 规范了:从站点 A 请求站点 B 的资源的时候,由于浏览器的同源策略的影响,这样的跨域请求将被禁止发送;为了让跨域请求能够正常发送,我们需要一套机制在不破坏同源策略的安全性的情况下、允许跨域请求正常发送,这样的机制就是 CORS。

2.预检请求
在 CORS 中,定义了一种预检请求,即 preflight request,当实际请求不是一个 简单请求 时,会发起一次预检请求。预检请求是针对实际请求的 URL 发起一次 OPTIONS 请求,并带上下面三个 headers :

        Origin:值为当前页面所在的域,用于告诉服务器当前请求的域。如果没有这个 header,服务器将不会进行 CORS 验证。
        Access-Control-Request-Method:值为实际请求将会使用的方法。
        Access-Control-Request-Headers:值为实际请求将会使用的 header 集合。
如果服务器端 CORS 验证失败,则会返回客户端错误,即 4xx 的状态码。

否则,将会请求成功,返回 200 的状态码,并带上下面这些 headers:

Access-Control-Allow-Origin:允许请求的域,多数情况下,就是预检请求中的 Origin 的值。
Access-Control-Allow-Credentials:一个布尔值,表示服务器是否允许使用 cookies。
Access-Control-Expose-Headers:实际请求中可以出现在响应中的 headers 集合。
Access-Control-Max-Age:预检请求返回的规则可以被缓存的最长时间,超过这个时间,需要再次发起预检请求。如果为0,则表示每次请求都需要进行预检
Access-Control-Allow-Methods:实际请求中可以使用到的方法集合浏览器会根据预检请求的响应,来决定是否发起实际请求。

3.解决方案

 @CrossOrigin 注解

使用 @CorssOrigin 注解需要引入 Spring Web 的依赖,该注解可以作用于方法或者类,可以针对这个方法或类对应的一个或多个 API 配置 CORS 规则:

@RestController
class HelloController {
    @GetMapping("hello")
    @CrossOrigin(origins = ["http://localhost:8080"])
    fun hello(): String {
        return "Hello, CORS!"
    }
}

 实现 WebMvcConfigurer.addCorsMappings 方法

WebMvcConfigurer 是一个接口,它同样来自于 Spring Web。我们可以通过实现它的 addCorsMappings 方法来针对全局 API 配置 CORS 规则:

@Configuration
@EnableWebMvc
class MvcConfig: WebMvcConfigurer {
    override fun addCorsMappings(registry: CorsRegistry) {
        registry.addMapping("/hello")
                .allowedOrigins("http://localhost:8080")
    }
}

注入 CorsFilter

CorsFilter 同样来自于 Spring Web,但是实现 WebMvcConfigurer.addCorsMappings 方法并不会使用到这个类,具体原因我们后面来分析。我们可以通过注入一个 CorsFilter 来使用它:

@Configuration
class CORSConfiguration {
    @Bean
    fun corsFilter(): CorsFilter {
        val configuration = CorsConfiguration()
        configuration.allowedOrigins = listOf("http://localhost:8080")
        val source = UrlBasedCorsConfigurationSource()
        source.registerCorsConfiguration("/hello", configuration)
        return CorsFilter(source)
    }
}

java过滤器过滤

允许整个项目跨域访问,可通过filter来进行过虑:

public class SimpleCORSFilter implements Filter{  
  
    @Override  
    public void destroy() {  
          
    }  
  
    @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-Methods", "POST, GET, OPTIONS, DELETE");  
            response.setHeader("Access-Control-Max-Age", "3600");  
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with");  
            chain.doFilter(req, res);  
          
    }  
  
    @Override  
    public void init(FilterConfig arg0) throws ServletException {  
          
    }  
  
}

在web.xml中需要添加如下配置:

<filter>  
      <filter-name>cors</filter-name>  
      <filter-class>com.ssm.web.filter.SimpleCORSFilter</filter-class>  
    </filter>  
    <filter-mapping>  
      <filter-name>cors</filter-name>  
      <url-pattern>/*</url-pattern>  
    </filter-mapping>
</filter>

为单个方法提供跨域访问,直接添加请求头:

       response.setHeader("Access-Control-Allow-Origin", "*");  
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");  
            response.setHeader("Access-Control-Max-Age", "3600");  
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

后台配置同源Cors (推荐)

在SpringBoot2.0 上的跨域 用以下代码配置 即可完美解决你的前后端跨域请求问题

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
 * 实现基本的跨域请求
 * @author linhongcun
 *
 */
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        /*是否允许请求带有验证信息*/
        corsConfiguration.setAllowCredentials(true);
        /*允许访问的客户端域名*/
        corsConfiguration.addAllowedOrigin("*");
        /*允许服务端访问的客户端请求头*/
        corsConfiguration.addAllowedHeader("*");
        /*允许访问的方法名,GET POST等*/
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

参考文章:

https://blog.csdn.net/weixin_32349093/article/details/112663167

https://blog.csdn.net/qq_37651267/article/details/93367870

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值