您现在的位置是:首页 > 文章详情

【重构】Spring Cloud OAuth 无Token调用源码封装

日期:2019-04-23点击:536

背景

重构-改善既有代码的设计,重构的目的是是软件更容易被理解和修改。

书接上回Spring Security OAuth 微服务内部Token传递的源码解析,本篇主要无token 调用过程中,代码的不断完善及其重构过程

需求很简单如下图,如果资源服务器的提供的接口,客户端不需要身份验证即不需要携带合法令牌也能访问,并且可以实现远程调用的安全性校验。

第一版本

资源服务器设置接口permitall,配置ignore url 即可

ignore-urls: - /actuator/** - /v2/api-docs 

保证A对外暴露,A --> B 暴露的服务接口安全

  • 自定义 @Inner
  • 校验逻辑,判断接口请求中是否含有 XX 请求头
/** * @author lengleng * <p> * 服务间接口不鉴权处理逻辑 */ @Slf4j @Aspect @Component @AllArgsConstructor public class PigxSecurityInnerAspect { private final HttpServletRequest request; @SneakyThrows @Around("@annotation(inner)") public Object around(ProceedingJoinPoint point, Inner inner) { String header = request.getHeader(SecurityConstants.FROM); if (inner.value() && !StrUtil.equals(SecurityConstants.FROM_IN, header)) { log.warn("访问接口 {} 没有权限", point.getSignature().getName()); throw new AccessDeniedException("Access is denied"); } return point.proceed(); } } 
  • 网关请求含有XX 的请求头,避免伪造
public class PigxRequestGlobalFilter implements GlobalFilter, Ordered { private static final String HEADER_NAME = "X-Forwarded-Prefix"; /** * Process the Web request and (optionally) delegate to the next * {@code WebFilter} through the given {@link GatewayFilterChain}. * * @param exchange the current server exchange * @param chain provides a way to delegate to the next filter * @return {@code Mono<Void>} to indicate when request processing is complete */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1. 清洗请求头中from 参数 ServerHttpRequest request = exchange.getRequest().mutate() .headers(httpHeaders -> {httpHeaders.remove(SecurityConstants.FROM);}) .build(); return chain.filter(exchange.mutate() .request(newRequest.mutate() .header(HEADER_NAME, basePath) .build()).build()); } @Override public int getOrder() { return -1000; } } 
  • 接口使用,首先声明 B服务的这个接口对外暴露
ignore-urls: - /info/* 
  • 接口使用,然后在 B服务的这个接口 添加@Inner注解
@Inner @GetMapping("/info/{username}") public R info(@PathVariable String username) { } 

重构

  • 上边第一版本的问题是,对于A/B 资源服务想对外暴露的接口,需要两步
  1. 声明在ResourceServerConfigurerAdapter 的 permitall
  2. B服务要再次添加@inner 注解

实现@Inner 一步到位到位

  • 在ignoreU日历 获取全部Controller 中,标志@Inner 注解的请求,自动维护到忽略的URL,减少开发配置
public class PermitAllUrlProperties implements InitializingBean { private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); @Autowired private WebApplicationContext applicationContext; @Getter @Setter private List<String> ignoreUrls = new ArrayList<>(); @Override public void afterPropertiesSet() { RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods(); map.keySet().forEach(info -> { HandlerMethod handlerMethod = map.get(info); // 获取方法上边的注解 替代path variable 为 * Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class); Optional.ofNullable(method) .ifPresent(inner -> info.getPatternsCondition().getPatterns() .forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, StringPool.ASTERISK)))); }); } } 
  • 核心是通过RequestMappingHandlerMapping 获取全部的路由配置,然后对 Requestmappint 设置的URL 进行规则替换,然后添加到 ignoreurl中,然后在注入到 ResourceServerConfigurerAdapter 进行permitall
  • 使用时候,如果是外部暴露
@Inner(value=false) 
  • 如果仅是服务内部调用暴露
@Inner 

总结

欢迎关注我们获得更多的好玩JavaEE 实践

原文链接:https://my.oschina.net/giegie/blog/3040796
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章