[Refactoring] Spring Cloud OAuth No Token Call Source Encapsulation

background

Refactoring - Improves the design of existing code so that software can be more easily understood and modified.

Book back Source Parsing for Token Pass-through within Spring Security OAuth Micro-Service In this article, there is no token call process, the code is constantly improving and its refactoring process.

The requirements are as follows: If the resource server provides an interface, the client does not need authentication, does not need to carry legal tokens to access it, and can implement security verification for remote calls.

First Version

Resource Server Set Interface permitall, Configure ignore url

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

Secure service interfaces exposed by A and A --> B

  • custom @Inner
  • Check logic to determine if an interface request contains a XX request header
/**
 * @author lengleng
 * <p>
 * Export unauthorized processing logic between services
 */
@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("Access Interface {} No privileges", point.getSignature().getName());
			throw new AccessDeniedException("Access is denied");
		}
		return point.proceed();
	}

}
  • Gateway requests contain XX request headers to avoid forgery
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 parameter in cleaning request head
		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;
	}
}
  • Interface use, first declare that this interface of the B service is exposed
ignore-urls:
- /info/*
  • The interface is used, and then the @Inner annotation is added to this interface of the B service
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {

}

Restructure

  • The problem with the first version above is that it takes two steps for A/B resource services to expose their interfaces
  1. Declare permitall in ResourceServerConfigurerAdapter
  2. B Service to be added again @inner annotation

Realization @Inner One step in place

  • In ignoreU Calendar Get All Controller s, Flag @Inner Annotation requests, automatic maintenance to ignored URL s, reduced development configuration
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);

			// Get the comment on the top of the method instead of path variable being *
			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))));
		});

	}
}
  • The core is to get all the routing configurations through RequestMappingHandlerMapping, and then to Requestmappint sets the URL for rule substitution, then adds it to ignoreurl, and then injects it into ResourceServerConfigurerAdapter for permitall
  • When used, if exposed externally
@Inner(value=false)
  • If only service internal call exposure
@Inner

summary

Welcome to our more fun JavaEE practices

Keywords: Spring Asterisk Vue JavaEE

Added by LaWr3nCe on Fri, 17 May 2019 10:57:55 +0300