目的

实现自定义的过滤规则,如token校验,权限校验等。

方法

实现GlobalFilter和Ordered。

GlobalFilter:公共过滤器

Ordered:过滤优先级,根据处理顺序修改大小。

  • 自定义过滤器
import com.gateway.code.ResponseCode;
import com.gateway.core.utils.PathUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;


/**
 * 访问权限校验
 * 通过验证jwt判断是否可以多路径进行访问
 *
 * @author: lizz
 * @date: 2020/1/20 9:46
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class);

    /**
     * 需要忽略auth校验的路径匹配集合
     */
    @Value("${auth.ignore}")
    private List<String> authIgnore;

    /**
     * 需要进行auth校验的路径匹配集合
     */
    @Value("${auth.rules}")
    private List<String> authRules;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        if (PathUtil.checkPath(request.getPath().value(),authRules,authIgnore)) {
            //get访问通过
            //其他访问方式返回401
            if(request.getMethod() == HttpMethod.GET){
                logger.info("fgwCheckAuth success:id={}", request.getId());
                return chain.filter(exchange);
            }else{
                logger.info("fgwCheckAuth failed:id={}", request.getId());
                return buildReqsponse(exchange.getResponse(), HttpStatus.UNAUTHORIZED,
                        ResponseCode.UNAUTH);
            }
        }else {
            //无需校验,直接返回
            return chain.filter(exchange);
        }
    }

    /**
     * 自定义返回结果
     * @param response
     * @param httpStatus
     * @param code
     * @return
     */
    public static Mono<Void> buildReqsponse(ServerHttpResponse response, HttpStatus httpStatus, ResponseCode code) {
        response.setStatusCode(httpStatus);
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("sever", "fw-gw");
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        String returnMsg = code.toString();
        DataBuffer bodyDataBuffer = response.bufferFactory().wrap(returnMsg.getBytes());
        return response.writeWith(Mono.just(bodyDataBuffer));
    }

    @Override
    public int getOrder() {
        //拦截器优先级,越小位最先执行
        return -179;
    }
}
  • PathUtil
import java.nio.file.FileSystems;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.List;

/**
 * 路径操作工具类
 *
 * @author: lizz
 * @date: 2020/1/9 11:17
 */
public class PathUtil {

    /**
     * 获取路径分段值
     * @param path 完整路径
     * @param num 第几分段
     * @return
     */
    public static String segment(String path, int num) {
        return path.split("/")[num];
    }

    /**
     * 路径分段中是否存在某个字符串
     * @param path 路径
     * @param key 匹配的字符串
     * @return
     */
    public static boolean exist(String path, String key) {
        String[] paths = path.split("/");
        for (String p : paths) {
            if (p.equals(key)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 多规则匹配
     *
     * @param rules 规则集合
     * @param path 路径
     * @return
     */
    public static boolean matches(List<String> rules, String path) {
        for(String rule : rules){
            if (matches(rule, path)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 路径匹配
     *
     * @param rule 规则
     * @param path 路径
     * @return
     */
    public static boolean matches(String rule, String path) {
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + rule);
        return matcher.matches(Paths.get(path));
    }

    /**
     * 过滤路径
     * @param path
     * @param rules
     * @param ignoreRules
     * @return
     */
    public static boolean checkPath(String path, List<String> rules,List<String> ignoreRules) {
        //是否匹配过滤路径
        if (rules.size() > 0 && PathUtil.matches(rules, path)) {
            //匹配到需要校验的规则
            //判断是否忽略
            if (ignoreRules.size() > 0
                    && PathUtil.matches(ignoreRules, path)) {
                //忽略路径
                return false;
            } else {
                //需要校验
                return true;
            }
        } else {
            //没有需要校验的路径
            return false;
        }
    }


}
  • ResponseCode
package com.gateway.code;

/**
 * 请求返回标准值
 * @author: lizz
 * @date: 2020/01/19 12:07
 */
public enum ResponseCode {
    //请求成功
    SUCCESS(0000, "请求成功"),
    //请求失败
    FAILED(1000, "请求失败"),
    //用户不存在
    NOT_USER(1001, "用户不存在"),
    //非法请求token
    ILLGAL(1002, "非法请求"),
    //非法签名
    ERROR_SIGN(1003, "非法签名"),
    //无访问权限
    UNAUTH(1004, "无权限");


    private Integer code;
    private String msg;

    ResponseCode(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }


    @Override
    public String toString() {
        return "{\"code\":" + this.code + ",\"msg\":\"" + this.msg + "\"}";

    }
}

配置:

#忽略路径规则
auth.ignore = /hi/login,/hi/login/**
#验证路径规则
auth.rules = /hi/**,/bye/**

 

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐