SpringCloud——Zuul

1、简介

Zuul是Netflix开源的微服务网关,可以和Eureka、Feign、Hystrix等组件配合使用。Zuul核心是一系列的过滤器,可以完成很多的功能。

  1. 身份认证与安全:识别每个资源的验证要求,并拒绝与要求不符的请求
  2. 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
  3. 动态路由:动态地将请求路由到不同不同的后端集群
  4. 压力测试:逐渐增加指向集群的流量,以了解性能
  5. 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
  6. 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群
  7. 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB使用的多样化,以及让系统的边缘更贴近系统的使用者

SpringCloud对Zuul进行了整合与增强, 不管是来自客户端的请求还是服务端内部自己调用,一切对服务的请求都会经过Zuul网关,然后由网关来实现鉴权、动态路由等等操作。Zuul就是服务的统一入口。

2、过滤器

Zuul作为网关中的一个重要功能,目的就是要实现请求的鉴权,这往往是通过Zuul提供的过滤器来实现的。

2.1、ZuulFilter

ZuulFilter是过滤器的最高级父类,其中有四个重要的方法。

public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {

    abstract public String filterType();//过滤器类型

    abstract public int filterOrder();//过滤器顺序
    
    boolean shouldFilter();// 来自IZuulFilter,要不要过滤

    Object run() throws ZuulException;// IZuulFilter,过滤逻辑
}
  • shouldFilter:返回的是一个boolean值,判断该过滤器是否执行,返回true表示执行
  • run:过滤器的具体业务逻辑
  • filterType:返回的是字符串,代表是过滤器的类型,其中包括四种类型:
    pre:请求在路由前执行
    route:路由请求时调用
    post:在routing和error过滤器之后调用
    error:处理请求时发生错误时调用
  • filterOrder:通过返回的int值来决定过滤器的执行顺序,数字越小优先级越高

2.2、自定义过滤器

首先导入依赖:

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

在yml文件中进行配置

server:
  port: 10011
spring:
  application:
    name: tensquare-manager
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8888/eureka/
  instance:
    prefer-ip-address: true
zuul:
  routes:
    tensquare-base:
      path: /base/**
      serviceId: tensquare-base
    tensquare-article:
      path: /article/**
      serviceId: tensquare-article
    tensquare-user:
      path: /user/**
      serviceId: tensquare-user

如果我们需要转发Authorization给该有的模块,做权限验证的话,就需要获得到Http请求的上下文,然后再传递给转发的模块。于是我们可以写一个在前台专门来获取request上下文并且转发的WebFilter。

@Component
public class WebFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //得到 request上下文
        RequestContext currentContext = RequestContext.getCurrentContext();
        //得到request域
        HttpServletRequest request = currentContext.getRequest();
        //得到头信息
        String header = request.getHeader("Authorization");
        //判断是否真的有头信息
        System.out.println(header);
        if (header != null && !"".equals(header)) {
            //把头信息继续向下传
            currentContext.addZuulRequestHeader("Authorization", header);

        }
        return null;
    }
}

获得了头信息间接的获取到了token给后端,现在要去把token解析出来,获取到用户的角色信心、权限信息等等。
使用无状态的jwt整合SpringSecurity去进行加密。

JWTUtil的工具类,yml配置等等就不说了,SpringSecurity整合jwt的无状态认证授权可以参考这篇文章。整合SpringSecurity随机加密的无状态认证授权
将Authorization的Header头信息传递下去,接下来需要对token进行解析,然后进行统一配置。通过getRole来获取到角色,然后进行统一的拦截就是相当于一个过滤器,因此将刚才的代码写到过滤器里面,写经由WebFilter传递token的后台过滤器ManagerFilter。

@Component
public class ManagerFilter extends ZuulFilter {

    @Autowired
    private JwtUtil jwtUtil;

    /**
     * 过滤是在请求前pre还是请求后post执行
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤器执行的顺序,数字越小越先执行
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 当前过滤器是否开启
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     *  过滤器内执行的逻辑,return任何object值都表示继续执行
     *  setsendzullResponse(false)表示不继续执行
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("经过了过滤器");
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();

        if (request.getMethod().equals("OPTIONS")) {
            return null;
        }

        if (request.getRequestURL().indexOf("login") > 0) {
            return null;
        }

        String header = request.getHeader("Authorization");
        if (header != null && !"".equals(header)) {
            if (header.startsWith("Broker ")) {
                String token = header.substring(7);
                try {
                    Claims claims = jwtUtil.parseJWT(token);
                    String roles = (String) claims.get("roles");
                    if (roles.equals("admin")) {
                        currentContext.addZuulRequestHeader("Authorization", header);
                        return null;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    currentContext.setSendZuulResponse(false);
                }
            }
        }
        currentContext.setSendZuulResponse(false);
        currentContext.setResponseStatusCode(403);
        currentContext.setResponseBody("权限不足");
        currentContext.getResponse().setContentType("text/html; charset=utf-8");
        return null;
    }
}

启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ManagerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ManagerApplication.class, args);
    }

    @Bean
    public JwtUtil jwtUtil(){
        return new JwtUtil();
    }
}

测试成功:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值