跨域过滤器相关问题整理

1.过滤器添加的方法

  1. SpringBoot的注解@CrossOrigin
@RestController
@CrossOrigin  
@RequestMapping("")
public class  TestController {
}
  1. 处理跨域请求的Configuration
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").
                allowedOriginPatterns("*"). // 重点。。允许跨域的域名,可以用*表示允许任何域名使用
//                allowedOrigins("*").    //在Springboot2.4对应Spring5.3后在设置allowCredentials(true)的基础上不能直接使用通配符设置allowedOrigins,而是需要指定特定的URL。如果需要设置通配符,需要通过allowedOriginPatterns指定
                allowedMethods("GET", "POST", "DELETE", "PUT") . //允许任何方法(post、get等)
                allowedHeaders("*"). //允许任何请求头
                allowCredentials(true). //带上cookie信息
                exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果


    }


}
  1. 过滤器(filter)的方式
@Component
public class CoresFilter implements Filter {
 

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
  1. CorsConfiguration和UrlBasedCorsConfigurationSource
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter  corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 允许cookies跨域
        config.setAllowCredentials(true); 
        // #允许向该服务器提交请求的URI,*表示全部允许,自定义可以添加多个,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
        config.addAllowedOrigin("*");
        // #允许访问的头信息,*表示全部,可以添加多个
        config.addAllowedHeader("*");
        // 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.setMaxAge(1800L);
        // 允许提交请求的方法,*表示全部允许,一般OPTIONS,GET,POST三个够了
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //对所有接口都有效
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
  1. 方法4 添加优先级
@Configuration
public class CorsConfig {
    @Bean
    public FilterRegistrationBean  corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 允许cookies跨域
        config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,自定义可以添加多个,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
        config.addAllowedHeader("*");// #允许访问的头信息,*表示全部,可以添加多个
        config.setMaxAge(1800L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许,一般OPTIONS,GET,POST三个够了
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);//对所有接口都有效
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); //注册到过滤器
        bean.setOrder(Ordered.LOWEST_PRECEDENCE); // 优先级最高
        return bean;
    }
}

注意
config.setAllowCredentials(true);
设置cookie后 addAllowedOrigin 会报错 替换使用 addAllowedOriginPattern
遇到问题
当前后端分离时 使用shiro做权限过滤

@Bean
    public FilterRegistrationBean delegatingFilterProxy() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName(SHIRO_FILTER_NAME);

        filterRegistrationBean.setFilter(proxy);
        filterRegistrationBean.setAsyncSupported(true);
        filterRegistrationBean.setEnabled(true);
        //这里开始未设置优先级
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
        return filterRegistrationBean;
    }

当验证token失效或者错误时候返回错误数据时候 前端总是会返回跨域问题。虽然设置跨域了但是失效。如果token验证正确 是可以请求到数据的
原因
添加过滤器的时候执行顺序错误
错误执行顺序shirofilter - corsfilter
如果shiro验证通过这样corsfilter会执行 跨域正常。
但是如果shiro验证失败返回错误 不会在走corsfilter的设置 这样前端会出现跨域问题。
解决办法修改执行顺序
corsfilter-shirofilter
让跨域设置优先执行
方法5可以设置执行顺序

 FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); //注册到过滤器
        bean.setOrder(Ordered.LOWEST_PRECEDENCE); // 优先级最高

保险起见把shirofilter注册时候设置的比corsfilter大一些(其实没必要)

shirofilter
 //这里开始未设置优先级
        filterRegistrationBean.setOrder(1);

注意:@Order、Ordered不影响类的加载顺序而是影响Bean加载到IOC容器之后执行的顺序(优先级);
有文章说@Order 无效 (没有具体验证 设置过一次好像确实没管用)
直接使用注册到过滤器方式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值