jwt可以理解为一个加密的字符串,里面由三部分组成:头部(header)、负载(payload)、签名(signature)
由ba64加密后的header和payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐cret组合加密,然后就构成了jwt字符串
往期介绍了jwt相关概念以及基本操作,接下来介绍如何在springboot中整合jwt实现登陆注册
<dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> <!--引入mybatis--> <dependency> <groupid>org.mybatis.spring.boot</groupid> <artifactid>mybatis-spring-boot-starter</artifactid> <version>2.1.3</version> </dependency> <!--引入mysql--> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>8.0.25</version> </dependency> <!--引入druid数据库连接池-->怎么防止别人蹭网 <dependency> <groupid>com.alibaba</groupid> <artifactid>druid</artifactid> <version>1.2.1</version> </dependency>行政管理培训 <!--引入lombok--> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> <version>1.18.12</version> </dependency> <dependency> <groupid>org.mybatis.spring.boot</groupid> <artifactid>mybatis-spring-boot-starter-test</artifactid> <version>2.1.3</version> </dependency> <!--引入jwt--> <dependency> <groupid>com.auth0</groupid> <artifactid>java-jwt</artifactid> <version>3.4.0</version> </dependency> </dependencies>
有一个jwt库,里面还有一个ur表
rver.port=8989spring.datasource.type=com.alibaba.dru广西工程职业技术学院id.pool.druiddatasourcespring.datasource.driver-class-name=com.mysql.cj.jdbc.driverspring.datasource.url=jdbc:mysql://localhost:3306/jwt?characterencoding=utf8&ussl=fal&rvertimezone=utc&rewritebatchedstatements=truespring.datasource.urname=rootspring.datasource.password=12345678#mybatis扫描的包mybatis.type-alias-package=com.ylc#mapper文件路径mybatis.mapper-locations=classpath:/**/*.xml#开启sql打印日志 logging.level后面是mybatis对应的方法接口所在的包logging.level.com.ylc.jwtdemo.dao=debug
import lombok.data;@datapublic class ur { private string urname; private string password; private int id;}
@mapperpublic interface urdao { ur login(ur ur);}
public interface urrvice { ur login(ur ur);//登录接口}
import java.util.hashmap;import java.util.map;@rvicepublic class urrviceimpi implements urrvice { @autowired private urdao urdao; @override public ur login(ur ur) { ur urdb=urdao.login(ur); if(urdb!=null) { map<string,string> map=new hashmap<>(); map.put("name",urdb.geturname()); return urdb; } throw new runtimeexception("登录失败"); }}
@restcontrollerpublic class urcontroller { @autowired private urrvice urrvice; @getmapping("/ur/login") public map<string,object> login(ur ur) { log.info("用户名:"+ur.geturname()); log.info("密码:"+ur.getpassword()); map<string,object> map=new hashmap<>(); try { urrvice.login(ur); map.put("msg","登录成功"); map.put("code","200"); } catch (exception ex) { map.put("msg","登录失败"); } return map; }}
<?xml version="1.0" encoding="utf-8"?><!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 指的是要配置的全限定类名--><mapper namespace="com.ylc.jwtdemo.dao.urdao"> <lect id="login" parametertype="com.ylc.jwtdemo.entity.ur" resulttype="com.ylc.jwtdemo.entity.ur"> lect *from ur where urname=#{urname} and password=#{password} </lect></mapper>
/** * jwt工具类 * @author yanglingcong * @date 2021/12/31 11:24 am */public class jwtutils { //鉴权 相当于私钥保存在服务器上 private static final string cret="##@$%@#s#ws"; /** * 生成token * @author yanglingcong * @date 2021/12/31 11:23 am * @param map * @return string */ public static string gettoken(map<string,string> map) { calendar instance=calendar.getinstance(); //默认七天过期 instance.add(calendar.date,7); //创建jwt jwtcreator.builder builder = jwt.create(); //payload map.foreach((k,v)->{ builder.withclaim(k,v); }); //指定令牌过期时间 builder.withexpiresat(instance.gettime()); string token=builder.sign(algorithm.hmac256(cret)); return token; } /** * 验证token * @author yanglingcong * @date 2021/12/31 11:26 am * @param token */ public static decodedjwt verify(string token) { return jwt.require(algorithm.hmac256(cret)).build().verify(token); }}
整个项目概览
测试验证是否能够连通数据库
访问:localhost:8989/ur/login?urname=ylc&password=123456
@slf4j@restcontrollerpublic class urcontroller { @autowired private urr强调英语vice urrvice; @getmapping("/ur/login") public map<string,object> login(ur ur) { log.info("用户名:"+ur.geturname()); log.info("密码:"+ur.getpassword()); map<string,object> map=new hashmap<>(); try { urrvice.login(ur); map.put("msg","登录成功"); map.put("code","200"); map<string,string> payload=new hashmap<>(); payload.put("name",ur.geturname()); string token= jwtutils.gettoken(payload); map.put("token",token); } catch (exception ex) { map.put("msg","登录失败"); } return map; } @postmapping("/test/verity") public map<string,string> veritytoken(string token) { map<string, string> map=new hashmap<>(); log.info("token为"+token); try { decodedjwt verify = jwtutils.verify(token); map.put("msg","验证成功"); map.put("state","true"); } catch (exception exception) { map.put("msg","验证失败"); exception.printstacktrace(); } return map; }}
访问:http://localhost:8989/ur/login?urname=ylc&password=123456
访问:http://localhost:8989/test/verity
但是我们这样写在实际项目中是不合理的,把token生成的代码放在了controller中,业务逻辑是不能放在controller层中的。假如很多接口都需要token来进行验证保护,那每一个接口都需要添加这样一段代码,造成代码冗余。
如果是web项目使用拦截器进行优化,如果是springcloud项目在网关层进行拦截,下面演示如何使用拦截器拦截
最好还把jwt生成token放在http请求头,这样就不需要把token当成参数传递了
新建一个拦截器jwtinterceptor
/** * jwt拦截器 * @author yanglingcong * @date 2021/12/31 12:39 pm */public class jwtinterceptor implements handlerinterceptor { @override public boolean prehandle(httprvletrequest request, httprvletrespon respon, object handler) throws exception { hashmap<string, string> map=new hashmap<>(); //从http请求头获取token string token = request.getheader("token"); try { //如果验证成功放行请求 decodedjwt verify = jwtutils.verify(token); return true; } catch (exception exception) { map.put("msg","验证失败:"+exception); } string json = new objectmapper().writevalueasstring(map); respon.tcontenttype("application/json:chart=utf=8"); respon.getwriter().println(json); return fal; }}
然后把拦截器注册到过滤器中,新建一个过滤器interceptconfig
/** * @author yanglingcong */@configurationpublic class interceptconfig implements webmvcconfigurer { @override public void addinterceptors(interceptorregistry registry) { //添加拦截器 registry.addinterceptor(new jwtinterceptor()) //拦截的路径 需要进行token验证的路径 .addpathpatterns("/test/verity") //放行的路径 .excludepathpatterns("/ur/login"); }}
登录是不需要拦截的,其他请求如果有需要验证token就放入拦截器的路径
在http请求头中放入token,会被拦截器拦截验证token的有效性
这就是springboot整合jwt实际项目一个大概的流程,但是细节方面cret(私钥)肯定每个用户都是不一样的,这里给写死了,而且私钥得保存在一个安全的地方。包括payload部分不能存放敏感的密码信息等等,还可以进行优化。
项目代码:https://gitee.com/yanglingcong/jwt-demo
到此这篇关于实战springboot集成jwt实现token验证的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 09:12:17,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/384b2dad9b2c84a9833975bcf90beb64.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:实战SpringBoot集成JWT实现token验证.doc
本文 PDF 下载地址:实战SpringBoot集成JWT实现token验证.pdf
留言与评论(共有 0 条评论) |