zuul+security跨域Cors问题解决

zuul+security跨域Cors问题解决

简介

场景

在服务后台都会出现跨域cors问题,不过一般spring解决起来比较方便,在框架+框架的基础上,问题就显得特别明显了,各种冲突,不了解源码的运行原理,解决起来也是有心无力。

这里介绍的是zuul配置了跨域,在前端调用仍然会出现跨域的问题。

一般没有权限的接口加上cors配置就会通过跨域的问题。不过在服务间调用具有权限的功能,莫名的报跨域问题。

post特殊请求

在解决问题时发现 post 请求也有点特殊,这里也需要处理一下。

post请求分为简单请求和复杂请求。

CORS 中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。

以及 OPTIONS 未携带任何权限相关的内容,会被认证拦截,我们也得放开 OPTIONS 类型请求

功能使用

Cross 解决

之前设置很简单,习惯操作把之前的代码复制了过来,第一次操作是创建了一个 CorsFilter bean,但是简单的请求确实通过了,不过权限接口过不了,于是按照一些资料配置了下面的代码 注入了 FilterRegistrationBean bean 还设置了 order 加载顺序。

解决后无果 仍然和之前的效果一致。

/**
 * 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Configuration
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig {

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("*"));
    config.setMaxAge(300L);

    source.registerCorsConfiguration("/**", config);
    CorsFilter corsFilter = new CorsFilter(source);
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(corsFilter);
    filterRegistrationBean.setOrder(0);
    return filterRegistrationBean;
  }
}

在一些资料+源码的帮助下,尝试了下面代码:

这次实现了 CorsFilter 类 加载了 @Order 顺序为 (Ordered.HIGHEST_PRECEDENCE) 最优先。

/**
 * 解决 zuul+oauth2 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AjaxCorsFilter extends CorsFilter {

  public AjaxCorsFilter() {
    super(configurationSource());
  }

  private static UrlBasedCorsConfigurationSource configurationSource() {
    CorsConfiguration corsConfig = new CorsConfiguration();
//        List<String> allowedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
    List<String> exposedHeaders = Arrays
        .asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
//        List<String> allowedMethods = Arrays.asList("POST", "GET", "DELETE", "PUT", "OPTIONS");

    List<String> allowedHeaders = Arrays.asList("*");
    List<String> allowedMethods = Arrays.asList("*");
    List<String> allowedOrigins = Arrays.asList("*");
    corsConfig.setAllowedHeaders(allowedHeaders);
    corsConfig.setAllowedMethods(allowedMethods);
    corsConfig.setAllowedOrigins(allowedOrigins);
    corsConfig.setExposedHeaders(exposedHeaders);
    corsConfig.setMaxAge(36000L);
    corsConfig.setAllowCredentials(true);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);
    return source;
  }
}

哈哈哈,解决了,但是有没有感觉到莫名其妙啊,经过了解

发现其实只是一个加载顺序的问题,我们上面注入的 FilterRegistrationBean 也可以使用的,只是在设置order的时候有点问题 需要设置比 security 优先级高,改为 Ordered.HIGHEST_PRECEDENCE 发现成功可以通过跨域了。

/**
 * 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Configuration
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig {

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("*"));
    config.setMaxAge(300L);

    source.registerCorsConfiguration("/**", config);
    CorsFilter corsFilter = new CorsFilter(source);
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(corsFilter);
    // 设置为 Ordered.HIGHEST_PRECEDENCE
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
  }
}

解决解决。。。

OPTIONS请求解决

有关 OPTIONS(NDN
web docs)
介绍。

在发送 post 请求 会发现在真正发送之前会有一个 OPTIONS 请求。

OPTIONS 为携带任何有状态的认证信息,被权限拦截下来异常,就没有之后的真正请求了。

我们只需要吧 OPTIONS 请求放开 返回200状态即可。

有很多办法做到,可以在zuul网关放过,也可以通过 security 添加 忽略拦截列表。

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
        // 添加忽略拦截OPTIONS 类型的请求
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
        ...
    }
}

万事大吉。

总结

简单的bug解决起来简单点,不过遇到交集的bug,有心无力的感觉,莫名其妙的问题,需要耐心观察源码运行原理。

示例代码地址:zuul-security

作者GitHub:
Purgeyao 欢迎关注

qq交流群: 812321371 微信交流群: MercyYao

微信公众号:

原文地址:https://www.cnblogs.com/Purgeyao/p/12038077.html

时间: 2024-08-29 16:45:21

zuul+security跨域Cors问题解决的相关文章

前后端分离下spring security 跨域问题等

最近在做一个项目,前后端分离,不可避免的遇到了跨域问题.起初是配置跨域: @Configurationpublic class CorsConfig extends WebMvcConfigurerAdapter { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("

jQuery 跨域访问问题解决方法

浏览器端跨域访问一直是个问题, 多数研发人员对待js的态度都是好了伤疤忘了疼,所以病发的时候,时不时地都要疼上一疼.记得很久以前使用iframe 加script domain 声明,yahoo js util 的方式解决二级域名跨域访问的问题. 时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了. 好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了跨域问题..有必要记下来备忘. 跨域的安全限制都是指浏

跨域CORS

一.跨域CORS是什么 当一个资源从与该资源本身所在的服务器的域或端口不同的域或不同的端口请求一个资源时,浏览器会发起一个跨域 HTTP 请求.出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求或者拦截了服务器返回内容.例如,XMLHttpRequest 和 Fetch 遵循同源策略.因此,使用 XMLHttpRequest或 Fetch 的Web应用程序只能将HTTP请求发送到其自己的域:这种安全机制是为避免出现类似CSRF 跨站攻击等问题. 二.实现CORS 根据CORS的定义和W3C

ASP.NET Core Web API 跨域(CORS) Cookie问题

身为一个Web API,处理来自跨域不同源的请求,是一件十分合理的事情. 先上已有的文章,快速复制粘贴,启用CORS: Microsoft:启用 ASP.NET Core 中的跨域请求 (CORS) ASP.NET Core 配置跨域(CORS) 如果按照以上文章,一步一步操作,你会发现,虽然能跨域请求了,但是即使客户端开了(xhr.withCredentials = true)也无法将Cookie发送给API. 关于AllowAnyOrigin 这是因为请求的首部中携带了 Cookie 信息,

转 Js 跨域CORS报错 Response for preflight has invalid HTTP status code 405

转自:http://www.cnblogs.com/SilenceTom/p/6697484.html 调用接口遇到Response for preflight has invalid HTTP status code 405这样的错误,是使用PUT方式提交请求接口.Content-Type设置为application/json,JS代码如下: $.ajax({ type: "PUT", url: "http://172.16.200.84:8977/Messages?ses

node跨域cors模块,nodejs+express跨域

使用express写的接口,只能在内部使用,如果想要外部的服务访问,就涉及到了跨域.但是又不想用jsonp,其实有一个node模块,可以轻松实现跨域 npm install cors --save 然后在app.js文件中 var cors = require('cors'); app.use(cors()); 注意,这个代码一定要,写在注册路由的前面.此模块也可以,当做路由中间件,指定某一个,或者某一部分路由,拥有跨域功能.

MVC跨域CORS扩展

CORS的原理: CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问.CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求.实现此功能非常简单,只需由服务器发送一个响应标头即可.      context.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", origin); 针对ASP.NET MVC,cors跨域访问,只需要在web.config中添加如下的内容即可 <syste

js Jquery 跨域请求问题解决

Chrome报错:跨域问题处理( Access-Control-Allow-Origin)_ 用于本地测试的快捷解决方法 报错提示如下: XMLHttpRequest cannot load http://www.xxxx.com/264/Data/GetScreenInfo. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not a

AJAX 跨域 CORS 解决方案

本篇文章由:http://xinpure.com/solutions-for-cross-domain-ajax-cors/ 两种跨域方法 在 Javascript 中跨域访问是比较常见的事情 就像现在比较流行写单页应用,而单页应用在访问 API 的时候就会有跨域的问题 要解决跨域的问题,其实也并不复杂,有两种方案可以选择 Jsonp 跨域 Jsonp 的实现原理就是:创建一个回调函数,然后在远程服务上调用这个函数并且将 JSON 数据形式作为参数传递,完成回调. CORS(跨域资源共享) 跨源