我是靠谱客的博主 超帅皮带,最近开发中收集的这篇文章主要介绍金融宝-Day4集成Redis缓存使用缓存获取数据阿里云存储OSS创建OSS微服务单点登录JWT令牌JWT测试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

集成Redis缓存

一、简介

1、场景

由于数据字典的变化不是很频繁,而且系统对数据字典的访问较频繁,所以我们有必要把数据字典的数据存入缓存,减少数据库压力和提高访问速度。这里,我们使用Redis作为系统的分布式缓存中间件。

2、RedisTemplate

在Spring Boot项目中中,默认集成Spring Data Redis,Spring Data Redis针对Redis提供了非常方便的操作模版RedisTemplate,并且可以进行连接池自动管理。

二、引入Redis

1、项目中集成Redis

service-base模块中添加redis依赖,Spring Boot 2.0以上默认通过commons-pool2连接池连接Redis

<!-- spring boot redis缓存引入 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 缓存连接池-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

<!-- redis 存储 json序列化 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

2、添加Redis连接配置

service-core 的 application.yml 中添加如下配置

#spring:
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
    password:  #默认为空
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0

3、启动Redis服务

远程连接Linux服务器或打开本地的redis-server.exe,启动服务

三、测试RedisTemplate

1、存值测试

test中创建测试类RedisTemplateTests

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTemplateTests {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private DictMapper dictMapper;
    @Test
    public void saveDict(){
        Dict dict = dictMapper.selectById(1);
        //向数据库中存储string类型的键值对, 过期时间5分钟
        redisTemplate.opsForValue().set("dict", dict, 5, TimeUnit.MINUTES);
    }
}

发现RedisTemplate默认使用了JDK的序列化方式存储了key和value

2、Redis配置文件

service-base 中添加RedisConfig,我们可以在这个配置文件中配置Redis序列化方案

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //首先解决key的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);

        //解决value的序列化方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型
        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);


        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

再次测试,key使用了字符串存储,value使用了json存储

3、取值测试

@Test
public void getDict(){
    Dict dict = (Dict)redisTemplate.opsForValue().get("dict");
    System.out.println(dict);
}

使用缓存获取数据

将数据字典存入redis

DictServiceImpl
注意:当redis服务器宕机时,我们不要抛出异常,要正常的执行后面的流程,使业务可以正常的运行

@Resource
private RedisTemplate redisTemplate;

@Override
public List<Dict> listByParentId(Long parentId) {
    //先查询redis中是否存在数据列表
    List<Dict> dictList = null;
    try {
        dictList = (List<Dict>)redisTemplate.opsForValue().get("srb:core:dictList:" + parentId);
        if(dictList != null){
            log.info("从redis中取值");
            return dictList;
        }
    } catch (Exception e) {
        log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));//此处不抛出异常,继续执行后面的代码
    }

    log.info("从数据库中取值");
    dictList = baseMapper.selectList(new QueryWrapper<Dict>().eq("parent_id", parentId));
    dictList.forEach(dict -> {
        //如果有子节点,则是非叶子节点
        boolean hasChildren = this.hasChildren(dict.getId());
        dict.setHasChildren(hasChildren);
    });

    //将数据存入redis
    try {
        redisTemplate.opsForValue().set("srb:core:dictList:" + parentId, dictList, 5, TimeUnit.MINUTES);
        log.info("数据存入redis");
    } catch (Exception e) {
        log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));//此处不抛出异常,继续执行后面的代码
    }
    return dictList;
}

阿里云存储OSS

一、开通“对象存储OSS”服务

为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案- 阿里云OSS。

二、控制台使用

创建Bucket

命名:jrb-file
读写权限:公共读

三、使用RAM子用户

1、进入子用户管理页面

2、添加用户

3、获取子用户key

AccessKeyId, AccessKeySecret
要及时保存AccessKeySecret

4、设置用户权限

AliyunOSSFullAccess

使用SDK访问OSS

一、使用SDK

在OSS的概览页右下角找到“Bucket管理”,点击“OSS学习路径”
点击“Java SDK”进入SDK开发文档

二、创建测试项目

1、创建Maven项目

2、配置pom

在Maven工程中使用OSS Java SDK,只需在pom.xml中加入相应依赖即可。以3.10.2版本为例,在<dependencies>中加入如下内容:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>

因为使用的是Java11,为Java 9及以上的版本,还需要添加jaxb相关依赖。添加jaxb相关依赖示例代码如下:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

三、测试用例

1、创建Bucket

package com.atguigu.aliyunoss;

public class OSSTest {

    // Endpoint以杭州为例,其它Region请按实际情况填写。
    String endpoint = "your endpoint";
    // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
    String accessKeyId = "your accessKeyId";
    String accessKeySecret = "your accessKeySecret";
    String bucketName = "jrb-file";

    @Test
    public void testCreateBucket() {        
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 创建存储空间。
        ossClient.createBucket(bucketName);

        // 关闭OSSClient。
        ossClient.shutdown();
    }
}

也可以在阿里云网站的UI界面创建

2、判断bucket是否存在

@Test
public void testExist() {
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

    boolean exists = ossClient.doesBucketExist(bucketName);
    System.out.println(exists);

    // 关闭OSSClient。
    ossClient.shutdown();
}

3、设置bucket访问权限

@Test
public void testAccessControl() {
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

    // 设置存储空间的访问权限为:公共读。
    ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);

    // 关闭OSSClient。
    ossClient.shutdown();
}

创建OSS微服务

一、新建云存储微服务

1、创建模块

service-oss

2、配置pom.xml

<dependencies>

    <dependency>
        <groupId>com.example</groupId>
        <artifactId>service-base</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--lombok用来简化实体类:需要安装lombok插件-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--aliyunOSS-->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
    </dependency>

    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
    </dependency>
    <!-- no more than 2.3.3-->
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
    </dependency>

    <!-- 日期工具栏依赖 -->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
    </dependency>

    <!--让自定义的配置在application.yaml进行自动提示-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

</dependencies>

3、配置application.yml

server:
  port: 8130 # 服务端口

spring:
  profiles:
    active: dev # 环境设置
  application:
    name: service-oss # 服务名

aliyun:
  oss:
    endpoint: 你的endponit
    keyId: 你的阿里云keyid
    keySecret: 你的阿里云keysecret
    bucketName: jrb-file

4、logback-spring.xml

修改日志路径为 jrb_log/oss

5、创建启动类

创建ServiceOssApplication.java

@SpringBootApplication
@ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
public class ServiceOssApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceOssApplication.class, args);
    }
}

6、启动项目

二、实现文件上传

1、从配置文件读取常量

创建常量读取工具类:OssProperties.java

@Setter
@Getter
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssProperties implements InitializingBean {
    private String endpoint;
    private String keyId;
    private String keySecret;
    private String bucketName;

    public static String ENDPOINT;
    public static String KEY_ID;
    public static String KEY_SECRET;
    public static String BUCKET_NAME;

    // 当私有成员被赋值后,此方法自动被调用,从而初始化常量
    @Override
    public void afterPropertiesSet() throws Exception {
        ENDPOINT = endpoint;
        KEY_ID = keyId;
        KEY_SECRET = keySecret;
        BUCKET_NAME = bucketName;
    }
}

2、文件上传业务

创建Service接口:FileService.java

public interface FileService {
    /**
     * 文件上传至阿里云
     */
    String upload(InputStream inputStream, String module, String fileName);
}

实现:FileServiceImpl.java
参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流

@Service
public class FileServiceImpl implements FileService {
    /**
     * 文件上传至阿里云
     */
    @Override
    public String upload(InputStream inputStream, String module, String fileName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(
                OssProperties.ENDPOINT,
                OssProperties.KEY_ID,
                OssProperties.KEY_SECRET);
        //判断oss实例是否存在:如果不存在则创建,如果存在则获取
        if(!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)){
            //创建bucket
            ossClient.createBucket(OssProperties.BUCKET_NAME);
            //设置oss实例的访问权限:公共读
            ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
        }

        //构建日期路径:avatar/2019/02/26/文件名
        String folder = new DateTime().toString("yyyy/MM/dd");

        //文件名:uuid.扩展名
        fileName = UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."));
        //文件根路径
        String key = module + "/" + folder + "/" + fileName;

        //文件上传至阿里云
        ossClient.putObject(OssProperties.BUCKET_NAME, key, inputStream);

        // 关闭OSSClient。
        ossClient.shutdown();

        //阿里云文件绝对路径
        return "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/" + key;
    }
}

3、控制层

创建controller.admin:FileController.java

@Api(tags = "阿里云文件管理")
@CrossOrigin //跨域
@RestController
@RequestMapping("/api/oss/file")
public class FileController {
    @Resource
    private FileService fileService;

    /**
     * 文件上传
     */
    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public R upload(
            @ApiParam(value = "文件", required = true)
            @RequestParam("file") MultipartFile file,

            @ApiParam(value = "模块", required = true)
            @RequestParam("module") String module)  {

        try {
            InputStream inputStream = file.getInputStream();
            String originalFilename = file.getOriginalFilename();
            String uploadUrl = fileService.upload(inputStream, module, originalFilename);

            //返回r对象
            return R.ok().message("文件上传成功").data("url", uploadUrl);
        } catch (IOException e) {
            throw new BusinessException(ResponseEnum.UPLOAD_ERROR, e);
        }
    }
}

4、Swagger测试

三、实现文件删除

1、业务层

Service接口:FileService.java

/**
     * 根据路径删除文件
     * @param url
     */
void removeFile(String url);

实现:FileServiceImpl.java

/**
     * 根据路径删除文件
     * @param url
     */
@Override
public void removeFile(String url) {

    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(
        OssProperties.ENDPOINT,
        OssProperties.KEY_ID,
        OssProperties.KEY_SECRET);

    //文件名(服务器上的文件路径)
    String host = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/";
    String objectName = url.substring(host.length());

    // 删除文件。
    ossClient.deleteObject(OssProperties.BUCKET_NAME, objectName);

    // 关闭OSSClient。
    ossClient.shutdown();
}

2、控制层

@ApiOperation("删除OSS文件")
@DeleteMapping("/remove")
public R remove(
    @ApiParam(value = "要删除的文件路径", required = true)
    @RequestParam("url") String url) {
    
    fileService.removeFile(url);
    return R.ok().message("删除成功");
}

单点登录

一、用户身份认证

1、单一服务器模式

一般过程如下:

  1. 用户向服务器发送用户名和密码。
  2. 验证服务器后,相关数据(如用户名,用户角色等)将保存在当前会话(session)中。
  3. 服务器向用户返回session_id,session信息都会写入到用户的Cookie。
  4. 用户的每个后续请求都将通过在Cookie中取出session_id传给服务器。
  5. 服务器收到session_id并对比之前保存的数据,确认用户的身份。

缺点:

  • 单点性能压力,无法扩展。
  • 分布式架构中,需要session共享方案,session共享方案存在性能瓶颈。

session共享方案:

  • session广播:性能瓶颈,不推荐
  • redis代替session:推荐,性能高

2、SSO(Single Sign On)模式

CAS单点登录、OAuth2

分布式,SSO(single sign on)模式:单点登录英文全称Single Sign On,简称就是SSO。它的解释是:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

  • 如图所示,图中有3个系统,分别是业务A、业务B、和SSO。
  • 业务A、业务B没有登录模块。
  • 而SSO只有登录模块,没有其他的业务模块。

一般过程如下:

  1. 当业务A、业务B需要登录时,将跳到SSO系统。
  2. SSO从用户信息数据库中获取用户信息并校验用户信息,SSO系统完成登录。
  3. 然后将用户信息存入缓存(例如redis)。
  4. 当用户访问业务A或业务B,需要判断用户是否登录时,将跳转到SSO系统中进行用户身份验证,SSO判断缓存中是否存在用户身份信息。
  5. 这样,只要其中一个系统完成登录,其他的应用系统也就随之登录了。这就是单点登录(SSO)的定义。

优点 :

  • 用户身份信息独立管理,更好的分布式管理。可以自己扩展安全策略

缺点:

  • 认证服务器访问压力较大。

3、Token模式

优点:

  • 无状态: token是无状态,session是有状态的
  • 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT)

缺点:

  • 占用带宽
  • 无法在服务器端销毁

JWT令牌

一、访问令牌的类型

二、JWT令牌

1、什么是JWT令牌

JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌。

JWT的使用场景:

  • 一种情况是webapi,类似之前的阿里云播放凭证的功能
  • 另一种情况是多web服务器下实现无状态分布式身份验证

JWT官网有一张图描述了JWT的认证过程

JWT的作用:

  • JWT 最重要的作用就是对 token信息的防伪作用

JWT的原理:

  • 一个JWT由三个部分组成:JWT头、有效载荷、签名哈希
  • 最后由这三者组合进行base64编码得到JWT

2、JWT令牌的组成

典型的,一个JWT看起来如下图:

https://jwt.io/

该对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。

每一个子串表示了一个功能块,总共有以下三个部分:JWT头、有效载荷和签名

JWT头

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

{
“alg”: “HS256”,
“typ”: “JWT”
}

在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

有效载荷

有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。

  • sub: 主题
  • iss: jwt签发者
  • aud: 接收jwt的一方
  • iat: jwt的签发时间
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

除以上默认字段外,我们还可以自定义私有字段,如下例:

{
“name”: “Helen”,
“admin”: true,
“avatar”: “helen.jpg”
}

请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

JSON对象也使用Base64 URL算法转换为字符串保存。

签名哈希

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。

首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。

HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(claims), secret) ==> 签名hash

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。

Base64URL算法

如前所述,JWT头和有效载荷序列化的算法都用到了Base64URL。该算法和常见Base64算法类似,稍有差别。

作为令牌的JWT可以放在URL中(例如api.example/?token=xxx)。 Base64中用的三个字符是"+","/“和”=",由于在URL中有特殊含义,因此Base64URL中对他们做了替换:"=“去掉,”+“用”-“替换,”/“用”_"替换,这就是Base64URL算法。

注意:base64编码,并不是加密,只是把明文信息变成了不可见的字符串。但是其实只要用一些工具就可以把base64编码解成明文,所以不要在JWT中放入涉及私密的信息。

3、JWT的用法

客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。

此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。

当跨域时,也可以将JWT放置于POST请求的数据主体中。

三、JWT问题和趋势

1、JWT默认不加密,但可以加密。生成原始令牌后,可以使用该令牌再次对其进行加密。

2、当JWT未加密时,一些私密数据无法通过JWT传输。

3、JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。

4、JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。

5、JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行身份验证。

6、为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

JWT测试

一、创建Maven项目

1、项目

项目类型:Maven

groupId:com.example
artifactId:jwt

2、基本依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

二、测试JWT

1、生成token

package com.example.jwt;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.Test;

import java.util.Date;
import java.util.UUID;

public class JwtTest {

    @Test
    public void testCreatedToken() {
        JwtBuilder jwtBuilder = Jwts.builder();
        // 头 载荷 签名哈希
        String jwtToken = jwtBuilder
                // 头
                .setHeaderParam("alg", "HS256")// 算法
                .setHeaderParam("typ", "JWT")// 令牌类型

                // 载荷 自定义信息
                .claim("nickname", "qy")
                .claim("avatar", "1.jpg")
                .claim("role", "admin")

                // 载荷 默认信息
                .setSubject("jrb-user") // 令牌主题
                .setIssuer("example") // 签发者
                .setAudience("example") // 接收方
                .setIssuedAt(new Date()) // 签发时间
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24)) // 令牌过期时间
                .setNotBefore(new Date(System.currentTimeMillis() + 1000 * 20)) // 生效时间
                .setId(UUID.randomUUID().toString())

                // 签名哈希
                .signWith(SignatureAlgorithm.HS256,"example123")

                // 组装JWT
                .compact();
        System.out.println(jwtToken);
    }
}

运行时报错,错误信息如下

Caused by: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter

原因是JDK版本过高,使用的是JDK11,JDK9及以上版本还需要添加jaxb相关依赖

<dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.3</version>
        </dependency>

2、解析token

@Test
    public void testGetInfo() {
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." +
                "eyJuaWNrbmFtZSI6InF5IiwiYXZhdGFyIjoiMS5qcGciLCJyb2xlIjoiYWRtaW4iLCJzdWIiOiJqcmItdXNlciIsImlzcyI6ImV4YW1wbGUiLCJhdWQiOiJleGFtcGxlIiwiaWF0IjoxNjMxNDE2NTAwLCJleHAiOjE2MzE1MDI5MDAsIm5iZiI6MTYzMTQxNjUyMCwianRpIjoiYzA4MDY2NTktNTZmMC00ODJlLTlmYTEtMDgzNzI3YTZhYWQ1In0." +
                "Wlc5jqd7jWBUB6LmkXdNX2xPjfNAP-OIj1cH64UXNgs";

        JwtParser jwtParser = Jwts.parser();
        Jws<Claims> claimsJws = jwtParser.setSigningKey("example123").parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        String nickname = claims.get("nickname",String.class);
        String avatar = claims.get("avatar",String.class);
        String role = claims.get("role",String.class);
        System.out.println(nickname + " " + avatar + " " + role);

    }

最后

以上就是超帅皮带为你收集整理的金融宝-Day4集成Redis缓存使用缓存获取数据阿里云存储OSS创建OSS微服务单点登录JWT令牌JWT测试的全部内容,希望文章能够帮你解决金融宝-Day4集成Redis缓存使用缓存获取数据阿里云存储OSS创建OSS微服务单点登录JWT令牌JWT测试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(199)

评论列表共有 0 条评论

立即
投稿
返回
顶部