前后端鉴权之jwt

699 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

1.知识点

  • 1 认证(authentication) & 鉴权(authorization) 认证:主要是确认身份

授权:授予对系统的访问权限

举个例子:张三登录教务系统,当输入用户名,密码(现在的登录一般都还需要输入验证码等)这是一个认证的过程 若认证成功,进入系统,而对每一种角色有不同的权限,学生只能看自己的成绩,其他同学的成绩不能查看 这就是权限。而今天讲的jwt则可以用来授权

  • 2 jwt 定义 JWT(JSON Web Token) 它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息.根据这个定义可以看出 传输对象是以json格式。

  • 3 应用场景 3.1 jwt可以用来授权 用户登录后 都带上这个jwt 用户则可以访问这个jwt允许的路由,服务,资源。(常见单点登录)

3.2 信息交换 因为jwt可以加密(对称加密:公用一个密钥 非对称加密:使用公钥/私钥),在信息传输的过程中验证信息的真伪性

  • 4 结构 jwt结构包含三部分:标题.有效载荷.签名 => xxxx.yyyy.zzzz

头部:一般由两部分组成:令牌类型(jwt);使用的签名算法(如:HMAC,RSA) 并把标题以Base64Url编码形成 JWT 的第一部分

eg: { "alg": "HS256", "typ": "JWT" }

有效载荷:简单理解:这里的信息是你想要携带的信息,比如像在jwt携带用户名,登录时间等 都可以再这里加上,但这里的信息最好是非机密信息,因为这个jwt是把相关信息加密了,所以改不容易,但读很容易

eg:其中有注册声明/公共声明

{ "sub": "1234567890", "name": "John Doe", "admin": true }

签名:创建签名部分,就是将前面两个一起加起来 看例子: 如果要使用 HMAC SHA256 算法,则签名将通过以下方式创建,其中secret则是在第一部分使用的签名算法

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

2.代码举例

简单的使用 结合springboot

1.写一个简单的工具类 利用jwt生成token; 验证token

public class JwtUtil {
    private String token;
    //生成token
    public static String CreateToken(TokenInfo tokenInfo){
        //对称算法 使用同一个密钥
        Algorithm algorithm = Algorithm.HMAC256("secret");
        String token = "";
        try{
            token = JWT.create().withIssuer(tokenInfo.getIssuer())
                    .sign(algorithm);

        }catch (JWTCreationException exception){
            throw new UserException("创建token失败:"+exception.getMessage());
        }
        return token;
    }


    //对token进行验证
    public static void verifyToken(String token){
        DecodedJWT decodedJWT = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256("secret")).build();
            decodedJWT = verifier.verify(token);
        }catch (Exception e){
            throw new UserException("token验证失败");
        }
    }
}

查看了一下jwt源码:其中JWT.create() JWT.java

image.png

JWTCreator.java(对于jwt的生成 主要就在这个java类中调用相应的方法)

image.png

当我们在登录的时候就可以直接调用JwtUtil.CreateToken来创建token,当有些功能只能有相应权限的人才能操作 则需要验证用户携带的jwt是否有该权限 JwtUtil.verifyToken

当用户登录后 都带上这个jwt 用户则可以访问这个jwt允许的路由,服务,资源,就例如一个系统,许多操作是必须要登录后才能访问,那我们可以设置一个统一的拦截器来拦截,若未登录就不能访问这些接口,若有自己自定义接口跳过认证则可以不用检查 代码如下:

@Component
public class JwtInterceptor implements HandlerInterceptor  {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) return  true;   // 如果不是映射到方法直接通过
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //检查是否有passtoken验证 若有直接跳过认证 其中passToken是自己自定义的一个注解
        if (method.isAnnotationPresent(PassToken.class)){
            PassToken annotation = method.getAnnotation(PassToken.class);
            if (annotation != null) return true;
        }
        if (token == null) throw new UserException("无token 请重新登陆");
        //验证token
        JwtUtil.verifyToken(token);

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}