package com.springboot.cloud.gateway.filter;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.springboot.cloud.auth.client.service.IAuthService;
import com.springboot.cloud.common.core.util.EncryptionUtil;
import com.springboot.cloud.gateway.service.IPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
@Configuration
@ComponentScan(basePackages = "com.springboot.cloud.auth.client")
@Slf4j
public class AccessGatewayFilter implements GlobalFilter {
private static final String X_CLIENT_TOKEN_USER = "x-client-token-user";
private static final String X_CLIENT_TOKEN = "x-client-token";
@Resource
private IAuthService authService;
@Resource
private IPermissionService permissionService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String authentication = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
String method = request.getMethodValue();
String url = request.getPath().value();
ServerRequest serverRequest = new DefaultServerRequest(exchange);
EncryptionUtil encryptionUtil = new EncryptionUtil();
if ("POST".equals(method) ) {
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
return Mono.just(body );
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
return chain.filter(exchange.mutate().request(decorator).build());
}));
}
log.debug("url:{},method:{},headers:{}", url, method, request.getHeaders());
if (authService.ignoreAuthentication(url)) {
return chain.filter(exchange);
}
if (permissionService.permission(authentication, url, method)) {
ServerHttpRequest.Builder builder = request.mutate();
builder.header(X_CLIENT_TOKEN, "添加服务间简单认证");
builder.header(X_CLIENT_TOKEN_USER, getUserToken(authentication));
return chain.filter(exchange.mutate().request(builder.build()).build());
}
return unauthorized(exchange);
}
private String getUserToken(String authentication) {
String token = "{}";
try {
token = new ObjectMapper().writeValueAsString(authService.getJwt(authentication).getBody());
return token;
} catch (JsonProcessingException e) {
log.error("token json error:{}", e.getMessage());
}
return token;
}
private Mono<Void> unauthorized(ServerWebExchange serverWebExchange) {
serverWebExchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
DataBuffer buffer = serverWebExchange.getResponse()
.bufferFactory().wrap(HttpStatus.UNAUTHORIZED.getReasonPhrase().getBytes());
return serverWebExchange.getResponse().writeWith(Flux.just(buffer));
}
}