JWT令牌实现登录授权

163 阅读2分钟

1、导入依赖

 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-api</artifactId>
     <version>0.12.6</version>
 </dependency>
 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-impl</artifactId>
     <version>0.12.6</version>
     <scope>runtime</scope>
 </dependency>
 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
     <version>0.12.6</version>
     <scope>runtime</scope>
 </dependency>

2、编写工具类

 public class JwtUtil {
 ​
     private static SecretKey getSigningKey(JwtProperties jwtProperties) {
         return Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(jwtProperties.getSecretKey()));
     }
 ​
     public static String generateToken(User user, JwtProperties jwtProperties) {
         return Jwts.builder()
                 .subject(user.getUsername())
                 .issuedAt(new Date())
                 .claim("userId", user.getId()) // 可以把"userId"替换成常量类中定义的常量,减少硬编码
                 .expiration(new Date(System.currentTimeMillis() + jwtProperties.getExpirationTime()))
                 .signWith(getSigningKey(jwtProperties), Jwts.SIG.HS256)
                 .compact();
     }
 ​
     public static Claims parseToken(String token, JwtProperties jwtProperties) {
         return Jwts.parser()
                 .verifyWith(getSigningKey(jwtProperties))
                 .build()
                 .parseSignedClaims(token)
                 .getPayload();
     }
 }

3、其它准备工作

3.1 创建JWT令牌所需的配置

 jwt:
   # jwt签名秘钥
   secret-key: HfkjksFKLJISJFKLFKWJFQFIQWIOFJQOFFQGGSDGFFJIQOEUFIEJFIOQWEFHFQOK5FKOIQWUF
   # 令牌过期时间
   expiration-time: 7200000
   # 前端传递过来的令牌名称
   token-name: token

3.2 编写配置属性类

作用:将配置文件中指定前缀的属性映射到该类的字段

 @Component
 @ConfigurationProperties(prefix = "jwt")
 @Data
 public class JwtProperties {
     private String secretKey;
     private long expirationTime;
     private String tokenName;
 }

3.3 统一返回结果类

 @Data
 public class Result<T> implements Serializable {
 ​
     private Integer code; // 响应码,1->成功;其它->失败
     private String msg;   // 错误信息
     private T data;       // 数据
 ​
     public static <T> Result<T> success() {
         Result<T> result = new Result<T>();
         result.code = 1;
         return result;
     }
 ​
     public static <T> Result<T> success(T object) {
         Result<T> result = new Result<T>();
         result.data = object;
         result.code = 1;
         return result;
     }
 ​
     public static <T> Result<T> error(String msg) {
         Result result = new Result();
         result.msg = msg;
         result.code = 0;
         return result;
     }
 }

3.4 常量类(非必须)

 public class JwtClaimsConstant {
     public static final String USER_ID = "userId";
 }

4、编写login方法,实现登录功能

4.1 Controller

 @RestController
 @RequestMapping("/user")
 @Api(tags = "员工管理")
 public class UserController {
 ​
     @Autowired
     private UserService userService;
     @Autowired
     private JwtProperties jwtProperties;
 ​
     @PostMapping("/login")
     @ApiOperation("用户登录")
     public Result<UserVO> login(@RequestBody UserDTO userDTO) {
         User user = userService.login(userDTO);
 ​
         //生成jwt令牌
         String token = JwtUtil.generateToken(user, jwtProperties);
 ​
         //封装VO对象
         UserVO userVO = UserVO.builder()
                 .id(user.getId())
                 .username(user.getUsername())
                 .password(user.getPassword())
                 .token(token)
                 .build();
 ​
         return Result.success(userVO);
     }
 }

4.2 Service

 public interface UserService {
     
     User login(UserDTO userDTO);
 }
 ​
 ​
 @Service
 public class UserServiceImpl implements UserService {
 ​
     @Autowired
     private UserMapper userMapper;
 ​
     @Override
     public User login(UserDTO userDTO) {
         String username = userDTO.getUsername();
         String password = userDTO.getPassword();
 ​
         User user = userMapper.getByUsername(username);
 ​
         //用户不存在
         if (user == null) {
             throw new RuntimeException("用户不存在");
         }
 ​
         //密码错误
         if (!password.equals(user.getPassword())) {
             throw new RuntimeException("密码错误");
         }
 ​
         return user;
     }
 }

4.3 Mapper

 @Mapper
 public interface UserMapper {
 ​
     @Select("select * from user where username = #{username}")
     User getByUsername(String username);
 }

5、启动程序,访问接口进行测试

 # 访问localhost:8080//user/login
 ​
 # 携带参数
 {
   "username": "john_doe",
   "password": "123456"
 }
 ​
 # 响应结果
 {
   "code": 1,
   "msg": null,
   "data": {
     "id": 1,
     "username": "john_doe",
     "password": "123456",
     "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE3NDExMDMzMjZ9.hKNE0RSsZtoKONNObNiYdigyd3zPJoOgLF1cl1uYJn0"
   }
 }