其他分享
首页 > 其他分享> > Springboot+getway横向切面拦截,并给post请求body赋值

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