app开发者平台在数字化时代的重要性与发展趋势解析
902
2022-11-10
实战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包
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.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
{
log.info("用户名:"+user.getUsername());
log.info("密码:"+user.getPassword());
Map
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
{
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
{
log.info("用户名:"+user.getUsername());
log.info("密码:"+user.getPassword());
Map
try {
userService.login(user);
map.put("msg","登录成功");
map.put("code","200");
Map
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
{
Map
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
//从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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~