springboot中JJWT的简单使用

springboot中JJWT的简单使用

一 什么是JWT

jwt全称json web token,是基于json协议的用于结局认证授权的方法。token就是令牌,其主要作用是用来进行授权(Authorization),授权和认证是不同的概念,认证是系统通过账号密码或其他手段来验证身份,授权是在认证后获得系统授予的权限。系统想知道用户有什么权限,需要给用户贴上标签,方式有很多种,token是其中一种。当用户获得token后,用户后续的请求只需附带token,系统便可进行授权。jwt不同与cookie-session,它不会在服务端进行储存,token会被写入进http请求的header或body中进行双向的传输。

JWT组成

JWT由三部分组成,分别是header,playload和signature。由于本文主要写JJWT的使用,JWT结构就不详细展开了,对于这部分还不了解的可以去JWT官网上查看,连接:JWT官网介绍

  • Header
  • PlayLoad
  • Signature

二 什么是JJWT

JJWT旨在成为最易于使用和理解的库,用于在JVM和Android上创建和验证JSON Web令牌(JWT)。 JJWT是完全基于JWT,JWS,JWE,JWK和JWA RFC规范以及Apache 2.0许可条款下的开源的纯Java实现。 该图书馆由Okta的高级建筑师Les Hazlewood创建,并由贡献者社区提供支持和维护。 Okta是面向开发人员的完整身份验证和用户管理API。 我们还添加了一些不属于该规范的便利扩展,例如JWS压缩和声明执行。

以上内容由jjwt官方文档机翻而来

简而言之,JJWT提供了java环境下的使用JWT的能力,使得具体实现对开发者透明,开发者只需用简单几行代码即可创建或者解析一个token。

三 简单入门

  1. 导入依赖(Maven环境)

    
    <dependency>
    	<groupId>io.jsonwebtokengroupId>
    	<artifactId>jjwtartifactId>
    	<version>0.9.0version>
    dependency>
    

    注意,现在jjwt已经更新到0.11.0,理论上说0.xx.x到0.xx.x的更新属于兼容性的,但经过尝试,发现还是有不少改动。这里也贴出来最新的版本的Maven工程依赖

    
    <dependency>
        <groupId>io.jsonwebtokengroupId>
        <artifactId>jjwt-apiartifactId>
        <version>0.11.1version>
    dependency>
    <dependency>
        <groupId>io.jsonwebtokengroupId>
        <artifactId>jjwt-implartifactId>
        <version>0.11.1version>
        <scope>runtimescope>
    dependency>
    <dependency>
        <groupId>io.jsonwebtokengroupId>
        <artifactId>jjwt-jacksonartifactId> 
        <version>0.11.1version>
        <scope>runtimescope>
    dependency>
    
  2. 生成token

    jjwt中,使用Jwts.builder()进行构建token。

    // 假设代码块被包含在一个函数中
    Map<String, Objcet> claims = new HashMap<>();
    // claims就是playload中的内容,可以写入自己需要的键值
    claims.put("key", "value");
    // 构建
    JwtBuilder jwtBuilder = Jwts.builder()
        		// 设置有效载荷
                .setClaims(claims)
        		// 设置subject
                .setSubject(subject)
        		// 设置签发时间
                .setIssuedAt(new Date())
        		// 采用HS256方式签名,key就是用来签名的秘钥
                .signWith(SignatureAlgorithm.HS256, key);
    // 调用compact函数将token打包成String并返回
    return jwtBuilder.compact();
    

    在上述代码块中,对JWT的playload进行了设置,没有自定义header。

    这里采用的HS256加密,HS256是一种对称秘钥加密手段,利用哈希MAC加密方式,即加密解密都使用相同的秘钥"key"。也可以采用RS256加密或者其他加密方法,RS256是公开秘钥加密,秘钥分为公钥和私钥,私钥用于生成JWT,公钥用于解密,想知道更具体的可以学习信息安全。但无论哪种加密方法,都得保护好秘钥,并确保秘钥难以被碰撞。

  3. 服务端发送token

    在步骤2中调用compact()会生成一长串经过编码的字符串,字符串格式为xxxxxx.xxxxxxxx.xxxxxxx,三个部分分别对应头,载荷和签名。将token发送给客户端往往通过httpheaders中的Authorization字段发送。当然也可以放在http数据包中发送给客户端。

    // 在header中写入Authorization
    @RequestMapping(value = "/jwttest1", method = RequestMethod.GET)
    public String test1(HttpServletRequest request, HttpServletResponse response) {
        // 通过步骤2中的方法获取token
        String token = ...
        response.setHeader("Authorization", token);
        return "success";
    }
    

    这里要注意,在前端如果是跨域请求,js获取heaer中隐私的信息在规范中是不安全的,所以服务器需设置,让这个header暴露出来

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .exposedHeaders("Authorization");
    }
    
  4. 服务端解析token

    发送token后,客户端的请求会附带token,token同样可以放httpheader中或报文中,接下来需要解析token

    @RequestMapping(value = "/jwttest2", method = RequestMethod.GET)
    public void test2(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("Authorization");
        // 调用下面写的方法解析即可,由于没有写方法的类,这里就不演示了
    }
    
    // 解析token
    public Claims jwtParser(String token) {
        Claims claims;
        // token不一定通过验证,所以需要包裹try-catch捕获jjwt提供的JwtException
        try {
            claims = Jwts.parser()
            	// HS256是对称加密体系,加密解密使用同一个key
                .setSigningKey(key)
                .parseClaimsJws(token)
                .getBody();
        } catch (JwtException e) {
            claims = null;
            e.printStackTrace();
        }
        return claims;
    }
    

    获取到的claims就是playload,如果是playload中的标准字段可以直接通过函数取出如

    String subject = (String) claims.getSubject();
    

    如果是自己自定义的键值可以通过get()方法取出,假设储存的值可以转换String

    String value = (String) claims.get("key");
    

    这样就获取到并解析了token。

你可能感兴趣的:(后端)