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