跨域问题

跨域问题

****************** 如有侵权请提示删除 *********************

方案一:addCorsMappings方法

/**
 * 跨域配置
 *
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

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

方案二:使用CorsFilter过滤器

使用addCorsMappings方法配置跨域时遇到的问题,
但是使用此方法配置之后再使用自定义拦截器时跨域相关配置就会失效。
原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入Mapping映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。

正确的解决跨域问题的方法时使用CorsFilter过滤器。代码如下:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
                .maxAge(3600);
    }
    
    private CorsConfiguration corsConfig() {
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    * 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等)
    */
    corsConfiguration.addAllowedOrigin("*");
    corsConfiguration.addAllowedHeader("*");
    corsConfiguration.addAllowedMethod("*");
    corsConfiguration.setAllowCredentials(true);
    corsConfiguration.setMaxAge(3600L);
    return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig());
    return new CorsFilter(source);
}
}

参考:
[心得]SpringBoot使用addCorsMappings配置跨域的坑_yookoo - SegmentFault 思否

【SpringMVC】与权限拦截器冲突导致的Cors跨域设置失效问题_MO的后端奇妙之旅 - SegmentFault 思否

springboot web跨域访问问题解决–addCorsMappings和CorsFilter_c5113620的博客-CSDN博客

方案三: 对于前端的OPTIONS请求

  • 疑问1:什么是options请求

OPTIONS请求方法的主要用途有两个:

1、获取服务器支持的HTTP请求方法;

2、用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

这是浏览器给我们加上的,后端并没有做任何操作。

  • 疑问2:为什么会用到options请求

这得从浏览器同源策略和跨域说起,具体可阅读也谈谈同源策略和跨域问题和浏览器同源政策及其规避方法,这里不在赘述。

解决跨域问题的方法有很多种,CORS是比较好的解决方案,我们的项目也是用的这种模式,这个模式会有”预检”的请求,也就是正常请求之前的options请求。

/**
*对于前端的OPTIONS请求,必须保持Access-Control-Request-Method,Access-Control-Request-Headers
 * 与Access-Control-Allow-Headers,Access-Control-Allow-Methods一致
*/
public class CorsFilter implements Filter {
	public CorsFilter() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)res;
		String method = request.getMethod();
		String accessControlRequestMethod = request.getHeader("Access-Control-Request-Method");
		String accessControlRequestHeaders = request.getHeader("Access-Control-Request-Headers");
		response.setHeader("Access-Control-Allow-Origin", "*");
		response.setHeader("Access-Control-Allow-Methods", accessControlRequestMethod);
		response.setHeader("Access-Control-Max-Age", "3600");
		response.setHeader("Access-Control-Allow-Credentials", "true");
		response.setHeader("Access-Control-Allow-Headers", accessControlRequestHeaders);
		if ("OPTIONS".equals(method)) {
			response.setStatus(HttpStatus.OK.value());
		} else {
			chain.doFilter(req, res);
		}

	}
	@Override
	public void destroy() {
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
}
/**
 * 跨域拦截器
 *
 */

@ConditionalOnProperty(
		value = {"tkp.cors.enable"},
		havingValue = "true"
)
@Configuration
public class CorsAutoConfiguration implements WebMvcConfigurer {
	public CorsAutoConfiguration() {
	}

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**")
				.allowedOrigins(new String[]{"*"})
				.allowCredentials(true)
				.allowedMethods(new String[]{"*"})
				.maxAge(3600L);
	}

	@Bean
	public FilterRegistrationBean corsWebFilter() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CorsFilter(), new ServletRegistrationBean[0]);
		filterRegistrationBean.setDispatcherTypes(
				DispatcherType.ASYNC, new DispatcherType[]{
						DispatcherType.ERROR,
						DispatcherType.FORWARD,
						DispatcherType.INCLUDE,
						DispatcherType.REQUEST});
		filterRegistrationBean.addUrlPatterns(new String[]{"/*"});
		return filterRegistrationBean;
	}
}

参考:
https://cloud.tencent.com/developer/article/1046663

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值