软件编程
位置:首页>> 软件编程>> java编程>> 实战SpringBoot集成JWT实现token验证

实战SpringBoot集成JWT实现token验证

作者:炒焖煎糖板栗  发布时间:2022-10-07 15:57:49 

标签:SpringBoot,JWT,token,实战

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

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

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

实战SpringBoot集成JWT实现token验证

环境搭建

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

<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>

2、数据库结构

实战SpringBoot集成JWT实现token验证

有一个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<String,String> 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<String,Object> login(User user)
   {
       log.info("用户名:"+user.getUsername());
       log.info("密码:"+user.getPassword());
       Map<String,Object> 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文件

<?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.UserDao">
   <select id="login" parameterType="com.ylc.jwtdemo.entity.User" resultType="com.ylc.jwtdemo.entity.User">
       select *from user where username=#{username} and password=#{password}
   </select>
</mapper>

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<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(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);
   }

}

整个项目概览

实战SpringBoot集成JWT实现token验证

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

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

实战SpringBoot集成JWT实现token验证

引入JWT

@Slf4j
@RestController
public class UserController {

@Autowired
   private UserService userService;

@GetMapping("/user/login")
   public Map<String,Object> login(User user)
   {
       log.info("用户名:"+user.getUsername());
       log.info("密码:"+user.getPassword());
       Map<String,Object> map=new HashMap<>();
       try {
           userService.login(user);
           map.put("msg","登录成功");
           map.put("code","200");

Map<String,String> 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<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/user/login?username=ylc&password=123456

实战SpringBoot集成JWT实现token验证

验证操作

访问:http://localhost:8989/test/verity

实战SpringBoot集成JWT实现token验证

但是我们这样写在实际项目中是不合理的,把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<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);
       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实现token验证

来源:https://www.cnblogs.com/cg-ww/p/15752750.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com