Apache ShenYu 网关 waf、rewrite、contextpath插件应用及源码分析

说明

  • 本文将分析 Apache ShenYu 网关 waf、rewirte、contextpath插件具体应用,以及对应的源码分析

waf插件

waf,全称 web application firewall,也就是web应用防火墙。网关作为我们服务的入口,加入waf可以为我们的服务提供各种安全验证和拦截。shenyu 网关的 waf插件,更是可以提供非常灵活的waf规则配置,我们甚至可以为每一个接口配置不同的策略。

插件应用
  • shenyu-admin -> 插件管理 -> waf 插件编辑 -> 开启插件
  • shenyu-bootstrap 加上 waf插件的stater依赖,并重启服务。
    <!-- shenyu waf plugin starter-->
    <dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-plugin-waf</artifactId>
    <version>${last.version}</version>
    </dependency>
    <!-- shenyu waf plugin end-->
  • 选择器配置请参考Apache ShenYu 网关选择器和规则解析
  • 规则配置:
    • Dealing: reject(拒绝),allow(允许)
    • status code: 如果拒绝,返回给请求方的code。

被waf拒绝后到返回值(code可以通过上面的方式自定义)

{"code":500,"message":" You are forbidden to visit","data":null}
源码分析

shenyu 网关 waf插件,在经过选择器和规则匹配上后,根据模式、规则的处理是拒绝还是允许,做对应的逻辑处理。拒绝,返回code和提示。允许,放行,流转到下一个插件。

核心源码:

public class WafPlugin extends AbstractShenyuPlugin {

    @Override
    protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
        ……
        //判断规则是拒绝,则直接返回错误信息
        if (WafEnum.REJECT.getName().equals(wafHandle.getPermission())) {
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
            Object error = ShenyuResultWrap.error(Integer.parseInt(wafHandle.getStatusCode()), Constants.REJECT_MSG, null);
            return WebFluxResultUtils.result(exchange, error);
        }
        return chain.execute(exchange);
    }
}

rewrite插件

rewrite插件提供对请求uri进行指定规则重写的功能

插件应用
  • shenyu-admin -> 插件管理 -> rewrite插件编辑 -> 开启插件
  • shenyu-bootstrap 项目中加入 rewrite插件依赖,并重启项目
    <!-- shenyu rewrite plugin start-->
    <dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-plugin-rewrite</artifactId>
    <version>${last.version}</version>
    </dependency>
    <!-- shenyu rewrite plugin end-->
  • 选择器配置请参考Apache ShenYu 网关选择器和规则解析
  • 规则配置:
    • rewriteURI: 重写后的uri
源码分析

rewrite插件的功能很简单,就是将服务选择器和规则配置的请求的uri替换为我们配置的 rewriteURI。核心源码如下:

public class RewritePlugin extends AbstractShenyuPlugin {
     @Override
    protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
        ……
        //将rewriteURI放到 web上下文的 属性中
        exchange.getAttributes().put(Constants.REWRITE_URI, rewriteHandle.getRewriteURI());
        return chain.execute(exchange);
    }
}

contextpath

contextpath插件提供网关重写请求路径的contextPath的功能

插件应用
  • shenyu-admin -> 插件管理 -> contextPath编辑 -> 开启插件

  • shenyu-bootstrap 添加相关依赖,并重启

    <!-- shenyu context_path plugin start-->
    <dependency>
    <groupId>org.apache.shenyu</groupId>
    <artifactId>shenyu-spring-boot-starter-plugin-context-path</artifactId>
    <version>${last.version}</version>
    </dependency>
    <!-- shenyu context_path plugin end-->
  • 选择器配置请参考Apache ShenYu 网关选择器和规则解析

  • 规则配置:

    • contextPath: 根据请求的Url截取自定义的contextPath获取真正的Url,例如请求路径为/shenyu/http/order, 配置的contextPath为’/shenyu/http’,那么真正请求的url为’/order’。
源码分析

当请求匹配到选择器和规则信息后,根据请求的Url截取自定义的contextPath获取真正的url,并替换为真正的url。核心源码:

public class ContextPathMappingPlugin extends AbstractShenyuPlugin {

    @Override
    protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {

        ……
        //处理context
        this.buildContextPath(shenyuContext, contextMappingHandle);
        return chain.execute(exchange);
    }

    private void buildContextPath(final ShenyuContext context, final ContextMappingHandle handle) {
        //handle.getRealUrl()是什么?页面配置规则的时候只有contextPath
        context.setContextPath(handle.getContextPath());
        if (!StringUtils.isBlank(handle.getRealUrl())) {
            log.info("context path mappingPlugin replaced old :{} , real:{}", context.getRealUrl(), handle.getRealUrl());
            context.setRealUrl(handle.getRealUrl());
            return;
        }
        ……
    }
}

从源码得知会从我们配置的realUrl中取真是的url,但是我们ontextPath页面规则配置只有配置一个contextPath参数。这是比较疑惑的地方。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注