实战SpringBoot集成JWT实现token验证

网友投稿 916 2022-11-10

实战SpringBoot集成JWT实现token验证

实战SpringBoot集成JWT实现token验证

目录环境搭建1、新建一个SpringBoot项目Jwt-Demo,引入项目后面需要用到的jar包2、数据库结构3、配置文件application.properties4、Entity包下新建一个User类5、Dao包下新建一个UserDao6、Service包下新建一个USerService7、UseService的实现类UserServiceImp8、controller包下新建一个UserController9、在resource文件夹下新建一个Usermapper文件10、JWT工具类JwtUtils引入JWT登录操作验证操作程序优化测试验证总结

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

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

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

环境搭建

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

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.3

mysql

mysql-connector-java

8.0.25

com.alibaba

druid

1.2.1

org.projectlombok

lombok

1.18.12

org.mybatis.spring.boot

mybatis-spring-boot-starter-test

2.1.3

com.auth0

java-jwt

3.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文件

select *from user where username=#{username} and password=#{password}

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:findAttribute方法的执行顺序
下一篇:信号量在多线程通讯运用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~