ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Springboot+getway横向切面拦截,并给post请求body赋值

2022-07-26 11:02:07  阅读:158  来源: 互联网

标签:body return Springboot exchange springframework getway org import String


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有