SpringBoot(二十三)SpringBoot集成JWT

devtools/2024/11/16 11:47:08/

最近整理完docker之后,突然想到,我是不是可以使用docker部署多个blog实例,来实现一下负载均衡呢?

现阶段,blog项目使用的是SESSION来做用户登录信息存储,如果配置负载均衡的话,那session其实就不是很适用了。没有办法跨实例共享。

那么该怎么办呢?很简单,使用JWT,那么何为JWT呢?

JWT(JSON WEB TOKEN)是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

上边这段话是我从百度上复制下来的。JWT简单讲就是一个加密字符串,跨语言,有过期时间。

下面我需要将现在blog中的session部分改成JWT来存储。

一:添加依赖

<!-- jwt       -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

二:添加JwtUtils.java

java">package com.springbootblog.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;public class JwtUtils
{//jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个private static final String secret_key = "camellia";// jwt过期时间(毫秒)private static final int ttl = 43200 * 1000;public static final String token_name = "token";/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥* @param claims    设置的信息* @return*/public static String createJWT(Map<String, Object> claims){// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;Date nowDate = new Date();// 生成JWT的时间long expMillis = System.currentTimeMillis() + JwtUtils.ttl;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 标记生成时间.setIssuedAt(nowDate)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, JwtUtils.secret_key.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** 重新生成token,根据之前的生成时间和过期时间* @param claims* @return*/public static String createJWTagain(Map<String, Object> claims,Date nowDate,Date expiration){// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 标记生成时间.setIssuedAt(nowDate)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, JwtUtils.secret_key.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(expiration);return builder.compact();}/*** Token解密* @param token     加密后的token* @return*/public static Claims parseJWT( String token){// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(JwtUtils.secret_key.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}/*** 验证token是否过期失效* @param expirationTime* @return*/public static boolean isTokenExpired (Date expirationTime) {return expirationTime.before(new Date());}/*** 获取jwt发布时间* @param token     token字符串*/public static Date getIssuedAtDateFromToken(String token) {return parseJWT(token).getIssuedAt();}/*** 获取jwt发布时间* @param token     token字符串*/public static Date getExpirationDateFromToken(String token) {return parseJWT(token).getExpiration();}
}

三:后端测试TOKEN生成及解析

java">@GetMapping("index/login")public Map<String, Object> login (@RequestParam("userName") String userName, @RequestParam("passWord") String passWord){// 声明返回mapMap<String, Object> result = new HashMap<>() ;// 声明加密参数mapMap<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("username","camellia");claims.put("url","https://guanchao.site");claims.put("age",25);String token= JwtUtils.createJWT(claims);//System.out.println("生成的jwt:"+token);Claims paramList = JwtUtils.parseJWT(token);System.out.println("解析后的token:"+paramList);System.out.println("解析后的token的id"+paramList.get("id"));System.out.println("解析后的token的有效期"+paramList.getExpiration());System.out.println("解析后的token的url"+paramList.get("url"));result.put("code", 200);result.put("token", token);return result ;}

理论上来说,到这里,后端的jwt集成就成功了。

四:前端VUE集成JWT

我的逻辑是,在登录成功接口中获取后端生成的TOKEN。将其存储到浏览器的缓存localstroage中。

每次请求的时候将TOKEN值从localstroage中取出,放入axios请求的header中。这部分放在axios封装中。

具体代码如何操作,请自行百度,我这里不做展示。

五:前端集成JWT后,后端测试JWT

java">public Map<String, Object> getFooterData(HttpServletRequest request)
{// 获取tokenString token = request.getHeader(JwtUtils.token_name);Object userid = "";Object figureurl = "";Object nickname = "";Object email = "";if(token.equals("") || token.equals("undefined") || token.equals("null") || token.equals(null)){}else{// 解析tokenClaims paramList = JwtUtils.parseJWT(token);userid = paramList.get("id");figureurl = paramList.get("figureurl");nickname = paramList.get("nickname");email = paramList.get("email");}Map<String,Object> result = new HashMap<>(12);// result.put("token",token);result.put("code",1);result.put("msg","操作成功!");result.put("visit",visit);result.put("friendLinklist",friendLinklist);result.put("article",article);result.put("user",user);result.put("message",message);result.put("userid",userid);result.put("figureurl",figureurl == null ? "" : figureurl);result.put("nickname",nickname);result.put("email",email);result.put("days",days);return result;
}

主要的部分都有注释,参照即可。

六:一些小问题

我的项目使用的是openjdk11,openjdk11集成JWT的时候发现一个小报错:

java">javax/xml/bind/DatatypeConverter

解决方式很简单,添加几个依赖就可以了:

java"><!-- jaxb依赖包 --><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-core</artifactId><version>2.3.0</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency>
<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.4.0-b180830.0438</version>
</dependency>

以上大概就是Springboot集成JWT的过程。

有好的建议,请在下方输入你的评论。


http://www.ppmy.cn/devtools/134421.html

相关文章

Redis 概 述 和 安 装

安 装 r e d i s: 1. 下 载 r e dis h t t p s : / / d o w n l o a d . r e d i s . i o / r e l e a s e s / 2. 将 redis 安装包拷贝到 /opt/ 目录 3. 解压 tar -zvxf redis-6.2.1.tar.gz 4. 安装gcc yum install gcc 5. 进入目录 cd redis-6.2.1 6. 编译 make …

C++ STL -- 模版

C STL&#xff08;标准模板库&#xff09;简介 C STL&#xff08;Standard Template Library&#xff09;是C的一部分&#xff0c;提供了一组通用的、可复用的组件&#xff0c;以简化编程过程。STL通过模板和泛型编程的方式&#xff0c;使得开发者可以使用预定义的数据结构与算…

【笔记】关于git和GitHub和git bash

如何推送更新的代码到github仓库 如何在此项目已经提交在别的远程仓库的基础上更改远程仓库地址&#xff08;也就是换一个远程仓库提交&#xff09; 如何删除github中的一个文件 第二版 删除github上的一个仓库或者仓库里面的某个文件_github仓库删除一个文件好麻烦-CSDN博客 …

sqlite更新

sqlite更新字段 UPDATE tab1SET field1 field1 || -,field2 field2 1WHERE ID < 10 或 UPDATE tab1SET (field1, field2) (field1 || -, field2 1)WHERE ID < 10 表关联更新 UPDATE tab1SET field1 (SELECT tab2.field3 FROM tab2 WHERE tab2.FID tab1.ID),WH…

Vue 3 条件渲染与列表渲染完整指南

Vue 3 条件渲染与列表渲染完整指南 在 Vue 3 中&#xff0c;v-if、v-show 和 v-for 是非常常用的指令&#xff0c;帮助我们实现条件渲染和列表渲染。本文将详细介绍这些指令的基本用法、适用场景、常见优化技巧和注意事项。 一、v-if 指令 1. v-if 基本用法 v-if 是一个用于…

llama factory lora 微调 qwen2.5 7B Instruct模型

项目背景 甲方提供一台三卡4080显卡 需要进行qwen2.5 7b Instruct模型进行微调。以下为整体设计。 要使用 LLaMA-Factory 对 Qwen2.5 7B Instruct模型 进行 LoRA&#xff08;Low-Rank Adapters&#xff09;微调&#xff0c;流程与之前提到的 Qwen2 7B Instruct 模型类似。LoRA …

MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下MathGPT的原理介绍&#xff0c;在中小学数学教学的应用场景&#xff0c;以及代码样例实现。MathGPT的核心架构是一个精心设计的多层次系统&#xff0c;旨在有效处理复杂的数学问题。其主要组成部分包括 数学知识图谱…

用OMS进行 OceanBase 租户间数据迁移的测评

基本概念 OceanBase迁移服务&#xff08;&#xff0c;简称OMS&#xff09;&#xff0c;可以让用户在同构或异构 RDBMS 与OceanBase 数据库之间进行数据交互&#xff0c;支持数据的在线迁移&#xff0c;以及实时增量同步的复制功能。 OMS 提供了可视化的集中管控平台&#xff…