Springboot+getway横向切面拦截,并给post请求body赋值
作者:互联网
1.getway+SpringCloud版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.4</version> <!--<version>1.5.9.RELEASE</version>--> <relativePath/> </parent> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>3.1.1</version> </dependency> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> <spring-cloud.version>2021.0.1</spring-cloud.version>
2.过滤器Getway
package com.cn.lze.filters; import com.alibaba.fastjson.JSON; import com.cn.lze.basic.LoginPermissions; import com.cn.lze.basic.Result; import com.cn.lze.dao.VisitUrlMapper; import com.cn.lze.entity.VisitUrl; import com.cn.lze.entity.VisitUrlExample; import com.cn.lze.utils.TokenUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage; import org.springframework.cloud.gateway.support.BodyInserterContext; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; 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.HandlerStrategies; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Objects; /** * @auther sunlongfei * create at 2022/6/27 10:21 * @pragram smart-park-parent * @description: 配置拦截权限 */ @Component @Slf4j public class GatewayFilter implements GlobalFilter,Ordered { @Autowired TokenUtils tokenUtils; @Autowired private RedisTemplate<Object,Object> redisTemplate; @Autowired private VisitUrlMapper visitUrlMapper; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); String url = request.getURI().toString(); log.info("接受到请求:{}",url); String path =request.getPath().toString(); log.info("接受到请求:{}",path); // log.info(RequestUtils.getIpAddress(request)); //跨行放行 if (request.getMethod() == HttpMethod.OPTIONS) { response.setStatusCode(HttpStatus.OK); return Mono.empty(); } VisitUrlExample example = new VisitUrlExample(); VisitUrlExample.Criteria criteria = example.createCriteria(); criteria.andUrlEqualTo(path); VisitUrl visitUrl =visitUrlMapper.selectOneByExample(example); //授权 String token = request.getHeaders().getFirst("token"); if((!(url.endsWith("/sysUser/getPubKey") || url.endsWith("/sysUser/getVerifyCode") || url.endsWith("/sysUser/login") || url.endsWith("/selectPage/list"))) && StringUtils.isNotBlank(token)){ if(!this.auth(exchange,chain)){ return this.responseBody(exchange, 406, "请先登录"); } LoginPermissions loginPermissions = this.getTenantKey(exchange,chain); if (loginPermissions == null) { return this.responseBody(exchange, 406, "请先登录"); } return this.operationExchange(exchange,chain,loginPermissions); } return chain.filter(exchange); } private Mono<Void> operationExchange(ServerWebExchange exchange, GatewayFilterChain chain,LoginPermissions loginPermissions) { // mediaType if ( HttpMethod.POST.equals(exchange.getRequest().getMethod())) { MediaType mediaType = exchange.getRequest().getHeaders().getContentType(); //重新构造request,参考ModifyRequestBodyGatewayFilterFactory ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders()); Mono<String> modifiedBody = serverRequest.bodyToMono(String.class) .flatMap(body -> { if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) { // 对原先的body进行修改操作 Map<String,String> map = JSON.parseObject(body,Map.class); map.put("tenant_key",loginPermissions.getTenantKey()); map.put("operator_no",loginPermissions.getUserCode()); map.put("operator_name",loginPermissions.getName()); String newBody = JSON.toJSONString(map); log.info(newBody); return Mono.just(JSON.toJSONString(map)); } return Mono.empty(); }); 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()); })); }else { //GET 验签 // MultiValueMap<String, String> map = exchange.getRequest().getQueryParams(); // map.add("tenant_key",tenantKey); try { String urlString = exchange.getRequest().getURI().toString(); String tenant_key =loginPermissions.getTenantKey(); if (urlString.contains("?")){ urlString = urlString+"&tenant_key="+tenant_key; }else { urlString = urlString+"?tenant_key="+tenant_key; } URI replaced = new URI(urlString); return chain.filter( exchange.mutate().request( new ServerHttpRequestDecorator(exchange.getRequest()){ /** * 这个是影响转发到后台服务的 uri * * @return */ @Override public URI getURI() { return replaced; } /** * 修改这个主要为了后面的Filter 获取查询参数是准确的 * @return */ @Override public MultiValueMap getQueryParams(){ return UriComponentsBuilder.fromUri(replaced).build().getQueryParams(); } }).build()); }catch (URISyntaxException e) { log.error("GET的请求方法报错",e); } } return chain.filter(exchange); } /** * 设置响应体 **/ public Mono<Void> responseBody(ServerWebExchange exchange, Integer code, String msg) { String message = JSON.toJSONString(new Result<>(code,msg)); byte[] bytes = message.getBytes(StandardCharsets.UTF_8); return this.responseHeader(exchange).getResponse() .writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap(bytes))); } /** * 设置响应体的请求头 */ public ServerWebExchange responseHeader(ServerWebExchange exchange) { ServerHttpResponse response = exchange.getResponse(); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json"); return exchange.mutate().response(response).build(); } private LoginPermissions getTenantKey(ServerWebExchange exchange, GatewayFilterChain chain){ ServerHttpRequest request =exchange.getRequest(); if(this.getAndValidationToken(request)){ String token = request.getHeaders().getFirst("token"); String username = tokenUtils.getUserName(token); if (StringUtils.isBlank(username)) { return null; } String authStr = redisTemplate.opsForValue().get(username).toString(); if(StringUtils.isBlank(authStr)){ return null; } LoginPermissions loginPermissions = JSON.parseObject(authStr,LoginPermissions.class); if (loginPermissions == null || StringUtils.isBlank(loginPermissions.getTenantKey()) || StringUtils.isBlank(loginPermissions.getUserCode())) { return null; } log.info("tenant_key的值:"+loginPermissions.getTenantKey()); return loginPermissions; } return null; } /** * 认证 * @return */ private boolean auth(ServerWebExchange exchange, GatewayFilterChain chain){ ServerHttpRequest request =exchange.getRequest(); if(this.getAndValidationToken(request)){ String token = request.getHeaders().getFirst("token"); String username = tokenUtils.getUserName(token); if (StringUtils.isBlank(username)) { return false; } String authStr =""; try { authStr = redisTemplate.opsForValue().get(username).toString(); }catch (Exception e) { log.error("获取用户权限信息失败",e); } if(StringUtils.isBlank(authStr)){ return false; } LoginPermissions loginPermissions = JSON.parseObject(authStr,LoginPermissions.class); if (loginPermissions == null || StringUtils.isBlank(loginPermissions.getTenantKey())) { return false; } log.info("tenant_key的值:"+loginPermissions.getTenantKey()); } return true; } /** * 获取并验证token * @return */ private boolean getAndValidationToken(ServerHttpRequest request){ String token = request.getHeaders().getFirst("token"); if (StringUtils.isBlank(token)) { return false; } //反正token是否正确 if(!tokenUtils.checkToken(token)){ return false; } //验证token是否过期 return (!tokenUtils.isJwtExpired(token)); } private Mono<Void> returnMono(GatewayFilterChain chain,ServerWebExchange exchange){ return chain.filter(exchange).then(Mono.fromRunnable(()->{ Long startTime = exchange.getAttribute("startTime"); if (startTime != null){ long executeTime = (System.currentTimeMillis() - startTime); log.info("耗时:{}ms" , executeTime); log.info("状态码:{}" , Objects.requireNonNull(exchange.getResponse().getStatusCode()).value()); } })); } private String modificationBody(String body){ log.info(body); return body; } @Override public int getOrder() { return -100; } }
标签:body,return,Springboot,exchange,springframework,getway,org,import,String 来源: https://www.cnblogs.com/slf784049656/p/16520157.html