background
Refactoring – To improve the design of existing code. The purpose of refactoring is to make the software easier to understand and modify.
The book is connected back to Spring Security OAuth micro service internal Token transfer source code analysis, this main tokeless call process, the continuous improvement of the code and its reconstruction process.
The requirement is very simple as shown in the figure below. If the interface provided by the resource server, the client can access it without authentication, that is, without carrying a valid token, and can realize security verification of remote invocation.
The first version
Resource server set interface permitall and configure ignore URL
ignore-urls:
- /actuator/**
- /v2/api-docs
Copy the code
Ensure the security of service interfaces exposed by A and B
- Custom @ Inner
- Verify the logic to determine whether the interface request contains XX request headers
/** * @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("No permission to access interface {}", point.getSignature().getName());
throw new AccessDeniedException("Access is denied");
}
returnpoint.proceed(); }}Copy the code
- The gateway requests headers containing XX 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. 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;
}
}
Copy the code
- Interface use, first declare that the interface of service B is exposed
ignore-urls:
- /info/*
Copy the code
- Interface, and then add the @inner annotation to this interface of the B service
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
}
Copy the code
refactoring
- The problem with the first version above was that there were two steps for the interfaces that A/B resource services wanted to expose
- Statement in ResourceServerConfigurerAdapter permitall
- The B service should add the @inner annotation again
Implement @inner in one step
- In the ignoreU calendar get all controllers, mark @inner annotation requests automatically maintained to ignored urls, reducing 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 methods annotation above alternative path variable to * 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)))); }); }}Copy the code
- Core is through the RequestMappingHandlerMapping access to all the routing configuration, and then to rules replace Requestmappint set the URL, and then added to the ignoreurl, And then injected into the ResourceServerConfigurerAdapter permitall
- Use when exposed if external
@Inner(value=false)
Copy the code
- If only internal service calls are exposed
@Inner
Copy the code
conclusion
- The above source code reference personal project based on Spring Cloud, OAuth2.0 development based on Vue separation of development platform
- QQ: 2270033969 Let’s talk about how you use Spring Cloud.
Stay tuned for more fun JavaEE practices