实战SpringBoot集成JWT实现token验证

本文详细讲解了SpringBoot集成JWT实现token验证,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

JWT可以理解为一个加密的字符串,里面由三部分组成:头部(Header)、负载(Payload)、签名(signature)

由base64加密后的header和payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了JWT字符串

往期介绍了JWT相关概念以及基本操作,接下来介绍如何在SpringBoot中整合JWT实现登陆注册

环境搭建

1、新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包

    org.springframework.bootspring-boot-starter-web org.springframework.bootspring-boot-starter-testtest org.mybatis.spring.bootmybatis-spring-boot-starter2.1.3 mysqlmysql-connector-java8.0.25 com.alibabadruid1.2.1 org.projectlomboklombok1.18.12 org.mybatis.spring.bootmybatis-spring-boot-starter-test2.1.3 com.auth0java-jwt3.4.0

2、数据库结构

有一个JWT库,里面还有一个User表

3、配置文件application.properties

server.port=8989 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/JWT?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true spring.datasource.username=root spring.datasource.password=12345678 #mybatis扫描的包 mybatis.type-aliases-package=com.ylc #mapper文件路径 mybatis.mapper-locations=classpath:/**/*.xml #开启sql打印日志  logging.level后面是mybatis对应的方法接口所在的包 logging.level.com.ylc.jwtdemo.dao=debug

4、Entity包下新建一个User类

import lombok.Data; @Data public class User { private  String username; private  String password; private  int id; }

5、Dao包下新建一个UserDao

@Mapper public interface UserDao { User login(User user); }

6、Service包下新建一个USerService

public interface UserService { User login(User user);//登录接口 }

7、UseService的实现类UserServiceImp

import java.util.HashMap; import java.util.Map; @Service public class UserServiceImpI implements UserService { @Autowired private UserDao userDao; @Override public User login(User user) { User userdb=userDao.login(user); if(userdb!=null) { Map map=new HashMap<>(); map.put("name",userdb.getUsername()); return userdb; } throw  new RuntimeException("登录失败"); } }

8、controller包下新建一个UserController

@RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/login") public Map login(User user) { log.info("用户名:"+user.getUsername()); log.info("密码:"+user.getPassword()); Map map=new HashMap<>(); try { userService.login(user); map.put("msg","登录成功"); map.put("code","200"); } catch (Exception ex) { map.put("msg","登录失败"); } return map; } }

9、在resource文件夹下新建一个Usermapper文件

  

10、JWT工具类JwtUtils

 /** * JWT工具类 * @author yanglingcong * @date 2021/12/31 11:24 AM */ public class JwtUtils { //鉴权 相当于私钥保存在服务器上 private  static  final String  secret="##@$%@#S#WS"; /** * 生成token * @author yanglingcong * @date 2021/12/31 11:23 AM * @param map * @return String */ public static  String getToken(Map 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(secret)); 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(secret)).build().verify(token); } }

整个项目概览

测试验证是否能够连通数据库

访问:localhost:8989/user/login?username=ylc&password=123456

引入JWT

@Slf4j @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/login") public Map login(User user) { log.info("用户名:"+user.getUsername()); log.info("密码:"+user.getPassword()); Map map=new HashMap<>(); try { userService.login(user); map.put("msg","登录成功"); map.put("code","200"); Map payload=new HashMap<>(); payload.put("name",user.getUsername()); String token= JwtUtils.getToken(payload); map.put("token",token); } catch (Exception ex) { map.put("msg","登录失败"); } return map; } @PostMapping("/test/verity") public  Map verityToken(String token) { Map 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/user/login?username=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(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HashMap 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); response.setContentType("application/json:charset=UTF=8"); response.getWriter().println(json); return false; } }

然后把拦截器注册到过滤器中,新建一个过滤器InterceptConfig

/** * @author yanglingcong */ @Configuration public class InterceptConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { //添加拦截器 registry.addInterceptor(new JwtInterceptor()) //拦截的路径 需要进行token验证的路径 .addPathPatterns("/test/verity") //放行的路径 .excludePathPatterns("/user/login"); } }

登录是不需要拦截的,其他请求如果有需要验证token就放入拦截器的路径

测试验证

在http请求头中放入token,会被拦截器拦截验证token的有效性

总结

这就是SpringBoot整合JWT实际项目一个大概的流程,但是细节方面secret(私钥)肯定每个用户都是不一样的,这里给写死了,而且私钥得保存在一个安全的地方。包括payload部分不能存放敏感的密码信息等等,还可以进行优化。

项目代码:https://gitee.com/yanglingcong/jwt-demo

到此这篇关于实战SpringBoot集成JWT实现token验证的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持0133技术站。

以上就是实战SpringBoot集成JWT实现token验证的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java