• 自定义Feign拦截器,解决微服务之间Feign调用请求头丢失问题


    在微服务开发过程中,安全方面使用的是Spring Security OAuth2.0令牌认证,在进行服务与服务之间调用时,使用的Feign客户端,如果不通过Feign拦截器来添加请求头信息。下游服务是接收不到认证过的token令牌,无法进行身份验证。

    1. 定义Feign拦截器,实现 RequestInterceptor 接口

      @Slf4j
      public class FeignRequestInterceptor implements RequestInterceptor {
          /**
           * 微服务之间传递的唯一标识
           */
          public static final String X_REQUEST_ID = "X-Request-Id";
      
          @Override
          public void apply(RequestTemplate template) {
      
              HttpServletRequest httpServletRequest = getHttpServletRequest();
      
              if (httpServletRequest != null) {
                  //获取头信息
                  Map<String, String> headers = getHeaders(httpServletRequest);
                  // 传递所有请求头,防止部分丢失
                  Iterator<Map.Entry<String, String>> iterator = headers.entrySet().iterator();
      
                  //将请求的头信息放入到RequestTemplate 的头信息中,当使用RequestTemplate发起请求时会自动添加头信息
                  while (iterator.hasNext()) {
                      Map.Entry<String, String> entry = iterator.next();
                      template.header(entry.getKey(), entry.getValue());
                  }
                  // 微服务之间传递的唯一标识,区分大小写所以通过httpServletRequest获取
                  if (httpServletRequest.getHeader(X_REQUEST_ID) == null) {
                      String sid = String.valueOf(UUID.randomUUID());
                      template.header(X_REQUEST_ID, sid);
                  }
                  log.debug("FeignRequestInterceptor:{}", template.toString());
              }
          }
      
          /**
           * RequestContextHolder 中获取 HttpServletRequest对象
           *
           * @return
           */
          private HttpServletRequest getHttpServletRequest() {
              try {
                  return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
              } catch (Exception e) {
                  return null;
              }
          }
      
          /**
           * 获取头信息
           *
           * @param request
           * @return
           */
          private Map<String, String> getHeaders(HttpServletRequest request) {
              Map<String, String> map = new LinkedHashMap<>();
              Enumeration<String> enumeration = request.getHeaderNames();
              if (enumeration != null) {
                  while (enumeration.hasMoreElements()) {
                      String key = enumeration.nextElement();
                      String value = request.getHeader(key);
                      map.put(key, value);
                  }
              }
              return map;
          }
      
      }
      
    2. 配置Bean

      @Bean
          @ConditionalOnMissingBean(FeignRequestInterceptor.class)
          public RequestInterceptor feignRequestInterceptor() {
      
              FeignRequestInterceptor interceptor = new FeignRequestInterceptor();
              log.info("FeignRequestInterceptor [{}]", interceptor);
              return interceptor;
          }
      

      在每次进行调用时,会经过 OAuth2AuthenticationProcessingFilter 过滤器的 doFilter方法进行token验证,通过 tokenExtract 的 extract 方法抽取携带在请求中的令牌信息。

    3. OAuth2AuthenticationProcessingFilter 的 doFilter
      在这里插入图片描述

      如果认证成功,放入SpringContext上下文中

      在这里插入图片描述

    充满鲜花的世界到底在哪里
  • 相关阅读:
    授权中的with admin option和with grant option
    CentOS6.2(64bit)下mysql5.6.16主从同步配置
    linux zip命令
    从模版中找到控件的方法和找到样式的方法
    WPF 在事件中绑定命令(不可以在模版中绑定命令)
    WPF: ShowDialog() 切换到其他应用窗口后,再切换回来无法让子窗口总在最上方
    TreeViewItem实现整行选中 (两种用法)
    BitmapImage 读取内存流和显示图片
    IsKeyboardFocused -- 键盘焦点
    WPF中的imagesource 和内存图片的处理
  • 原文地址:https://www.cnblogs.com/aliases/p/14693292.html
Copyright © 2020-2023  润新知