第十四节 JWT在Zuul网关中的应用

亮子 2021-06-09 03:01:25 17673 1 1 0

1、JWT的生成

1)、引入依赖

我们使用JJWT的包,来实现JWT功能,目前最新版是0.9.1,官网如下:

https://github.com/jwtk/jjwt

修改server-blog-user工程的pom.xml依赖如下:

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

2)、增加生成JWT的接口

    @RequestMapping(value = "/getToken")
    @ResponseBody
    public Object getToken() {
        // http://localhost:8000/getToken

        JwtBuilder builder = Jwts.builder();
        builder.setId("888888");              //设置唯一编号
        builder.setSubject("田不平");         //设置主题  可以是JSON数据
        builder.setIssuedAt(new Date());      //设置签发日期

        // 设置过期时间(300秒)
        long now = System.currentTimeMillis();
        long exp = now+1000*300;
        builder.setExpiration( new Date( exp ) );

        // 增加角色设置
        builder.claim( "roles","admin" );

        // 设置签名 使用HS256算法,并设置SecretKey(字符串)
        builder.signWith(SignatureAlgorithm.HS256,"shenmazong");

        // 构建 并返回一个字符串
        String token = builder.compact();
        System.out.println(token);

        return token;
    }

3)、运行效果

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODg4ODgiLCJzdWIiOiLnlLDkuI3lubMiLCJpYXQiOjE1NzY4OTIwMzMsImV4cCI6MTU3Njg5MjMzMywicm9sZXMiOiJhZG1pbiJ9.5NbfHd4MX_4vWUT2NQYMepfX1QUhaO10WO-9TekJKJw

2、Zuul过滤器验证和转发JWT

1)、修改UserController类

    @RequestMapping(value = "/verifyToken")
    @ResponseBody
    public Object verifyToken() {
        // http://localhost:8000/verifyToken
        String token = request.getHeader("token");
        if(StringUtils.isNotBlank(token)) {
            System.out.println(token);
        }
        else {
            System.out.println("没有token,验证失败");
            return null;
        }

        try {
            Claims claims = Jwts.parser()
                    .setSigningKey("shenmazong")
                    .parseClaimsJws(token)
                    .getBody();
            System.out.println(claims);

            System.out.println("id=" + claims.getId());
            System.out.println("sub=" + claims.getSubject());
            System.out.println("time=" + claims.getIssuedAt());

            System.out.println("roles=" + claims.get("roles"));
        }
        catch (ExpiredJwtException e) {
            System.out.println("token expired");
        } catch (SignatureException e) {
            System.out.println("token signature error");
        } catch (Exception e) {
            System.out.println("token error");
        }

        System.out.println("token,验证成功");
        return "token,验证成功";
    }

2)、修改zuul过滤器

(1)拦截http协议的head信息

    /**
     * 执行过滤逻辑
     * @return
     */
    @Override
    public Object run() throws ZuulException {

        System.out.println("Zuul 网关过滤器...");
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = request.getHeader("token");
        System.out.println("Zuul 网关过滤器,token"+token);

        return null;
    }

(2)拦截请求的参数

    //编写过滤器拦截业务逻辑代码
    @Override
    public Object run() throws ZuulException {
        //案例:拦截所有的服务接口,判断服务接口上是否有传递userToken参数。
        //1.获取上下文
        RequestContext currentContext = RequestContext.getCurrentContext();
        currentContext.getResponse().setContentType("text/html;charset=UTF-8");

        //2.获取Request对象
        HttpServletRequest request = currentContext.getRequest();

        //3.获取token的时候从请求头中获取
        String userToken = request.getParameter("userToken");
        if (StringUtils.isEmpty(userToken)){
            //不会继续执行....不会去调用服务接口,网关服务直接响应给客户端
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseBody("{name:'david'}");
            currentContext.setResponseStatusCode(401);
            return null;
        }
        //正常执行调用其他服务接口...
        return null;
    }

3)、运行效果

通过Postman发送两次请求,第一次head中没有token,第二次请求有token。

(1)网关运行效果

图片alt

(2)user项目运行结果

图片alt