springboot解决CORS跨域请求的三种方法

springboot解决CORS跨域请求的三种方法

前段时间,由于公司的项目采用前后端分离开发,前端和后端部署在不同的服务器上,导致前段不能正常访问后端,原因是后端没有开放CORS跨域请求。

CORS跨域请求简介

1、js跨域请求:

     只要协议、域名、端口有任何一个不同,都被当作是不同的域。

2、跨域调用测试:

前端控制台出现 以下信息,表示不能跨域访问:

  No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9100' is therefore not allowed access. The response had HTTP status code 400.

3、跨域解决方案 CORS

       CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

请求过程如下图:

https://i-blog.csdnimg.cn/blog_migrate/1a29a38f1eec0aa7d1c5b02ef3390184.png

Preflight Request:

https://i-blog.csdnimg.cn/blog_migrate/857245ae379797bff0eea6bd027e8205.png

然后服务器端给我们返回一个Preflight Response

https://i-blog.csdnimg.cn/blog_migrate/abcf7042a37e108400f5d06ea5f6989b.png

解决方案:

方案一:

使用spring 标签,注意spring的版本高于4.2

@CrossOrigin(origins="http://localhost:9105",allowCredentials="true")。

示例:

在Controller的方法上加上@CrossOrigin注解,

@CrossOrigin(origins = "*",allowCredentials ="true")

@GetMapping("/assetList")

public Result list(){
    return new Result();
}

方案二:

通过继承WebMvcConfigurationSupport类,然后重写addCorsMappings方法,

示例:

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.CorsRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;



@Configuration

public class WebMvcConfig extends WebMvcConfigurationSupport {



    @Override

    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/**")

                .allowCredentials(true)

                .allowedMethods("*")

                .allowedOrigins("*")

                .allowedHeaders("*");

}

}

方案三:

自定义过滤器filter,然后在filter中拦截cors请求,并设置响应头:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String origin = request.getHeader("Origin");
        if(!StringUtils.isEmpty(origin)){
            //cors请求
            System.out.println("cors请求");
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods","*");
            response.setHeader("Access-Control-Allow-Headers","*");
            if (request.getMethod().equals("OPTIONS")) {
                response.setStatus(HttpServletResponse.SC_ACCEPTED);
            }
        }

        filterChain.doFilter(request,response);
    }
}

在springboot中,我们可以通过org.springframework.web.filter.CorsFilter类来实现,

CorsFilter类需要CORS配置才能正常工作,CORS配置对应的类是org.springframework.web.cors.CorsConfigurationSource。

示例:

import org.springframework.boot.web.servlet.FilterRegistrationBean;

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;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;



@Configuration

public class WebMvcConfig extends WebMvcConfigurationSupport {

   

    /**

     * 处理跨域请求

     * @return

     */

    @Bean

    public FilterRegistrationBean corsFilter() {

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);

        config.addAllowedOrigin("*");

        config.addAllowedHeader("*");

        config.addAllowedMethod("*");

        source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效

        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));

        bean.setOrder(0);

        return bean;

    }

}

补充:推荐使用Filter的方式处理跨域问题,比如全局异常处理器拦截到的异常信息返回前端时,如果需要跨域则“方案二”可能无效,使用下列代码即可解决问题:


    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

本人水平有限,代码有不足之处还请大家见谅,欢迎大家提建议。本人目前主要方向是Java,如果有兴趣,可以一起交流,

Java成长交流学习群:184998348

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值