VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • 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));
        }
    }
}

 



相关教程