当前位置: 首页 > news >正文

SpringBoot集成JWT token实现权限验证

JWT=JSON Web Token

1. JWT的组成

JWT==Header,Payload,Signature==>abc.def.xyz

地址:JSON Web Tokens - jwt.er

1.1 Header

Header:标头。

两个组成部分:令牌的类型(JWT)和所使用的签名算法,经过Base64 Url编码后形成的JWT的第一部分。

{"type":"JWT","alg":"HS256"
}

1.2 Payload

Payload---有效负载。存放用户自定义消息

注意点:是以明文的形式进行展示,以Base64进行编码。

{“sub":"123","name":"jon","admin":true
}

1.3 Signature

signature--签名。使用标头的算法和私钥对第一部分和第二部分进行加密,通过Base64 Url编码后形成JWT的第三部分。

var encodeString =base64UrlEncode(header)+"."+base64UrlEncode(payload);
var signature=HMACSHA356(encodeString,secret);

2.JWT的基本使用

1.导入pom JWT依

JDK1.8以下的加入JWT依赖即可

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

JDK1.8以上的加上其他

        <!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><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>

2.创建JWT

    //毫秒private long time=1000*60*60*24;//签名private String signature="admin";/*JWT加密*/@Testpublic void jwt(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken = jwtBuilder//header:头部.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload:载荷.claim("username", "tom").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis() + time))//设置id字段.setId(UUID.randomUUID().toString())//signature:签名//注意点:这个签名算法要与前面的算法一致//设置加密算法和签名.signWith(SignatureAlgorithm.HS256, signature)//将前面3个重要信息拼接起来,使用”."来连接.compact();System.out.println(jwtToken);}

3.验证JWT

    @Test/*验证JWT*/public void checkJwt(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2OTM2MzgzMDMsImp0aSI6ImU5ZjY3ZjBhLWE0NTAtNGYzYy1hYTY3LTU3ZGMwOWRjMDM4ZCJ9.FxA5c91E2bk2KW1rdMo8jlmClXgn7r2mVSaXs19Qzzk";//Jwts.parser():解析JwtParser jwtParser = Jwts.parser();//验证该token是否符合JWT规则boolean result = Jwts.parser().isSigned(token);System.out.println(result);//true}

4.解析JWT

    @Test/*解析JWT*/public void parseJwt(){String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2OTM2MzgzMDMsImp0aSI6ImU5ZjY3ZjBhLWE0NTAtNGYzYy1hYTY3LTU3ZGMwOWRjMDM4ZCJ9.FxA5c91E2bk2KW1rdMo8jlmClXgn7r2mVSaXs19Qzzk";//获取JWT的解析对象JwtParser jwtParser = Jwts.parser();//通过signature对token进行签名,解开//parseClaimsJws:将JWT转换为key-value的形式,通过key来获取对应的value//Jws<Claims>:类似于Map集合Jws<Claims> claimsJws = jwtParser.setSigningKey(signature).parseClaimsJws(token);//获取Jws对象中的数据:get(key)表示根据key来获取value//相当于将header和payload封装为一个claimsClaims claims = claimsJws.getBody();//存储的是用户保存的数据Object username = claims.get("username");System.out.println(username);Object role = claims.get("role");System.out.println(role);String id = claims.getId();System.out.println(id);//签名String subject = claims.getSubject();System.out.println(subject);//有效期Date time = claims.getExpiration();System.out.println(time);}

3.SpringBoot + vue +JWT

 1.导入pom JWT依

JDK1.8以下的加入JWT依赖即可

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

JDK1.8以上的还要加上以下依赖

        <!--JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><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>

2.导入工具类

public class JwtUtil {//毫秒private static long time=1000*60*60*24;//签名private static String signature="admin";public static String createToken(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken=jwtBuilder//header.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload.claim("username", "admin").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis()+time)).setId(UUID.randomUUID().toString())//signature//注意点:这个签名算法要与前面的算法一致.signWith(SignatureAlgorithm.HS256,signature)//将前面3个重要信息拼接起来.compact();return jwtToken;}
}

3.在后台解决跨域问题

@Configuration//配置类
public class CoreConfiguration implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")//所有接口.allowCredentials(true)//是否发送Cookie.allowedOriginPatterns("*")//支持域.allowedMethods("GET","POST","PUT","DELETE")//支持方法.allowedHeaders("*").exposedHeaders("*");}
}

4.前台登录界面

5.前端代码

  methods:{handleSubmit(){this.$refs.ruleForm.validate((valid)=>{if(valid){let _this=thisaxios.get("http://localhost:8080/login",{param:_this.ruleForm}).then(function (response){console.log(response.data)})}})}}

6.进行路由跳转,并且将用户信息存到本地存储中

JSON.stringify-->将JSON转换为字符串

    handleSubmit(){this.$refs.ruleForm.validate((valid)=>{if(valid){let _this=thisaxios.get("http://localhost:8080/login",{param:_this.ruleForm})./*带着用户输入的用户名和密码*/then(function (response){console.log(response.data)//如果data不为空,则表示登录成功if(response.data!=null){//使用localStorage//将JSON转换为字符串localStorage.setItem('access-admin',JSON.stringify(response.data))//跳转到首页_this.$router.replace({path:"/"})}})}})}

7.将用户信息展示到页面中

JSON.parse--->将字符串转换为JSON

<template>
<div>欢迎回来:{{admin.username}}
</div>
</template>data(){return{admin:''}},created() {
//获取数据this.admin=JSON.parse(window.localStorage.getItem("access-admin"));},

8.添加验证用户信息是否存在【在路由中写】

/router/index.js

router.beforeEach((to,from,next)=>{if(to.path.startsWith('/login')){window.localStorage.removeItem('access-admin')next()}else {let admin=JSON.parse(window.localStorage.getItem('access-admin'))if(!admin){next({path:'/login'})}else {//校验token合法性axios({url:'http://localhost:8080/checkeToken',method:'get',headers:{token:admin.token}}).then((response)=>{if(!response.data){console.log("校验失败");next({path:'/error'})}})}}
})

9.后端验证Token方法

UserController

    /*** 验证token方法*/@GetMapping("/checkToken")public Boolean checkToken(HttpServletRequest request){//因为前端是将数据存储在header,所以我们要是有getHeaderString token = request.getHeader("token");return JwtUtil.checkToken(token);}

JwtUtil

    /*** 校验token是否正确*/public static boolean checkToken(String token){if (token==null){return false;}try {//解析Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}

4.Springboot+JWT

User

@Data
public class User {private String username;private String password;private String token;
}

UserController:生成JWT令牌

public class UserController {private final String USERNAME = "admin";private final String PASSWORD = "123123";@GetMapping("/login")public User login(User user){//判断是否正确if(USERNAME.equals(user.getUsername()) && PASSWORD.equals(user.getPassword())){//添加token;token保存到user对象//定义一个工具类,将生成JWTuser.setToken(JwtUtil.createToken());return user;}return null;}
}

JwtUtil:生成JWT令牌

public class JwtUtil {//毫秒private static long time=1000*60*60*24;//签名private static String signature="admin";public static String createToken(){//构建JWT对象:Jwts.builder()JwtBuilder jwtBuilder = Jwts.builder();String jwtToken=jwtBuilder//header.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")//payload.claim("username", "admin").claim("role", "admin").setSubject("admin-test")//有效时间===>一天=当前时间+24小时//获得当前的系统时间:System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis()+time)).setId(UUID.randomUUID().toString())//signature//注意点:这个签名算法要与前面的算法一致.signWith(SignatureAlgorithm.HS256,signature)//将前面3个重要信息拼接起来.compact();return jwtToken;}
}

【前端直接传递token】

JwtUtil:验证JWT是否过期

    /*** 校验token是否过期*/public static boolean checkToken(String token){if (token==null || token==""){return false;//false表示令牌过期}try {//拿到JWT对象Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}

UserController:验证JWT是否过期

    /*** 验证token是否过期:前端传递token*/@GetMapping("/checkToken")public Boolean checkToken(String token){return JwtUtil.checkToken(token);}

【将Token放入请求头中,使用request】

 JwtUtil:验证JWT是否过期

    /*** 校验token是否过期*/public static boolean checkToken(String token){if (token==null || token==""){return false;//false表示令牌过期}try {//拿到JWT对象Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);}catch (Exception e){e.printStackTrace();}return true;}

UserController:验证JWT是否过期

    /*** 验证token是否过期:前端将数据封装在请求头中* @param request* @return*/public boolean checkToken(HttpServletRequest request){//getHeader中的key要与前端通过一致String token = request.getHeader("token");//key-->tokenreturn JwtUtil.checkToken(token);}

解决跨域问题

参考:SpringBoot跨域请求的问题_m0_63077733的博客-CSDN博客

@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 所有接口.allowCredentials(true) // 是否发送 Cookie.allowedOriginPatterns("*") // 支持域.allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法.allowedHeaders("*").exposedHeaders("*");}
}

拦截器实现Token验证

@Configuration
public class TokenInterceptor implements HandlerInterceptor {//在请求处理方法被调用之前被调用@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//前提:token放在请求头中String token = request.getHeader("token");if (!JwtUtil.checkToken(token)) {return false;//验证失败}return true;}
}

http://www.lryc.cn/news/154652.html

相关文章:

  • 算法通关村第11关【青铜】| 位运算基础
  • 无涯教程-Android - RadioGroup函数
  • 降噪音频转录 Krisp: v1.40.7 Crack
  • 基于React实现:弹窗组件与Promise的有机结合
  • docker使用(一)生成,启动,更新(容器暂停,删除,再生成)
  • 用Qt自制一个小闹钟
  • Vue2.0/Vue3.0使用xlsx+xlsx-style实现导出Excel文件
  • 【Kafka系列】(一)Kafka入门
  • 外包干了2个月,技术退步明显了...
  • python实现语音识别
  • java八股文面试[多线程]——线程的状态
  • Go学习[合集]
  • 代码随想录算法训练营第42天 | ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集
  • 解决DNS服务器未响应错误的方法
  • SpringBoot的HandlerInterceptor拦截器使用方法
  • java 常用 jar 包
  • C#面试十问
  • Day 41 动态规划part03 : 343. 整数拆分 96.不同的二叉搜索树
  • 四轴飞行器的电池研究(MatlabSimulink仿真)
  • 准备HarmonyOS开发环境
  • Java 面试 - Redis
  • 【Go 基础篇】Go语言结构体之间的转换与映射
  • Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
  • 将 ordinals 与 比特币智能合约集成 : 第 1 部分
  • 【USRP】集成化仪器系列1 :信号源,基于labview实现
  • 串行协议——USB驱动[基础]
  • 健康舒适的超满意照明体验!SUKER书客SKY护眼台灯测评
  • PID 算法
  • 13.Redis 事务
  • 李宏毅机器学习课程笔记(更新ing)