• springboot~某个接口模拟登录并同步给feign


    功能

    1. 某个rest接口是公开的,它的feign服务的接口需要授权
    2. 重写一个HttpServletRequestWrapper,实现模拟登录之后把header头进行填充
    3. 接口请求上下文里的token,通过Feign拦截器转给每个feign请求上下文
    4. 完成对feign接口的自动授权访问 

    重写HttpServletRequestWrapper

    /**
     * 自定义的请求上下文.
     */
    public class CustomHttpServletRequest extends HttpServletRequestWrapper {
    
        private Map<String, String> headers = new HashMap<>();
    
        public CustomHttpServletRequest(HttpServletRequest request) {
            super(request);
        }
    
        public void addHeader(String name, String value) {
            headers.put(name, value);
        }
    
        @Override
        public String getHeader(String name) {
            String value = super.getHeader(name);
    
            if (headers.containsKey(name)) {
                value = headers.get(name);
            }
    
            return value;
        }
    
        @Override
        public Enumeration<String> getHeaderNames() {
            List<String> names = Collections.list(super.getHeaderNames());
            names.addAll(headers.keySet());
    
            return Collections.enumeration(names);
        }
    
        @Override
        public Enumeration<String> getHeaders(String name) {
            List<String> list = Collections.list(super.getHeaders(name));
    
            if (headers.containsKey(name)) {
                list.add(headers.get(name));
            }
    
            return Collections.enumeration(list);
        }
    }
    

    建立过滤器

    @Component
    public class CustomFilter implements Filter {
        @Autowired
        KcUserClient kcUserClient;
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            CustomHttpServletRequest request = new CustomHttpServletRequest((HttpServletRequest) servletRequest);
            request.addHeader("Authorization", "Bearer " + login().getAccessToken());
            filterChain.doFilter(request, servletResponse);
        }
    
        public KeycloakAccessToken login() {
            // 登陆参数省略
            var result = kcUserClient.login(authTokenRequest);
            return result;
        }
    }
    

    WebMvcConfigurer里注册

    /add接口进行配置

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Resource
        private CustomFilter customFilter;
    
        @Bean
        public FilterRegistrationBean<CustomFilter> initFilterRegistrationBean() {
            FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(customFilter);
            registrationBean.addUrlPatterns("/add");
            registrationBean.setOrder(0);
            return registrationBean;
        }
    }
    

    Feign拦截器的配置

    /**
     * @description: Feign内部调用时带上请求头信息
     * 注意:要去yml里面改变hystrix Feign的隔离策为strategy: SEMAPHORE
     **/
    @Configuration
    public class FeignConfiguration implements RequestInterceptor {
    
        @Override
        public void apply(RequestTemplate template) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    String values = request.getHeader(name);
                    template.header(name, values);
                }
            }
            Enumeration<String> bodyNames = request.getParameterNames();
            StringBuffer body = new StringBuffer();
            if (bodyNames != null) {
                while (bodyNames.hasMoreElements()) {
                    String name = bodyNames.nextElement();
                    String values = request.getParameter(name);
                    body.append(name).append("=").append(values).append("&");
                }
            }
            if (body.length() != 0) {
                body.deleteCharAt(body.length() - 1);
                template.body(body.toString());
            }
        }
    }
    

    上面代码完成了对/add接口的拦截,通过自动授权,完成对授权接口kcUserClient.addUser();调用。

    KcUserClient内容

    @FeignClient(name = "keycloak", url = "http://192.168.4.26:8080/auth", configuration = KcUserClient.Configuration.class)
    public interface KcUserClient {
        @PostMapping("/admin/realms/demo/users")
        ResponseEntity<?> addUser(@RequestBody UserDTO userDTO);
    
        @RequestMapping(value = "/realms/demo/protocol/openid-connect/token",
                method = RequestMethod.POST,
                consumes = "application/x-www-form-urlencoded")
        KeycloakAccessToken login(@RequestBody AuthTokenRequest authTokenRequest);
    
        /**
         * 转向器.
         */
        class Configuration {
            @Bean
            Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
                return new SpringFormEncoder(new SpringEncoder(converters));
            }
        }
    }
    

  • 相关阅读:
    2020.2.5随笔
    2020.2.4
    2020.2.3随笔
    2020.2.2随笔
    2020/2/1随笔
    python3 百度AI-v3之 人脸对比 & 人脸检测 & 在线活体检测 接口
    python:Json模块dumps、loads、dump、load介绍
    python3之selenium.webdriver 库练习自动化谷歌浏览器打开百度自动百度关键字
    python之https爬虫出现 SSL: CERTIFICATE_VERIFY_FAILED (同时打开fiddler就会出现)
    调试python 程序的几种方法总结
  • 原文地址:https://www.cnblogs.com/lori/p/14445790.html
Copyright © 2020-2023  润新知