一.登录接口
1.接口参数
请求路径:/login
请求参数:username和password
反应参数:json格式的
"id": 1,
"username": "songjiang",
"name": "宋江",
"token": "..."
2.编写代码
1.请求参数和反应参数的实体
请求参数LoginDTO
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class LoginDTO {
private String username;
private String password;
}
反应参数LoginVO
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class LoginVO {
private Integer id;
private String username;
private String password;
private String token;
}
2.定义一个loginController
@RestController
@Slf4j
public class LoginController {
@Autowired
EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO){
log.info("loginDTO:{}",loginDTO);
LoginVO loginVO = empService.login(loginDTO);
return Result.success(loginVO);
}
}
3.实现login方法,并在登陆成功之后发放Token,然后封装入LoginVO
@Override
public LoginVO login(LoginDTO loginDTO) {
//验证用户名和密码是否填写
String username = loginDTO.getUsername();
String password = loginDTO.getPassword();
if(StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
throw new RuntimeException("用户名或密码不能为空");
}
// 验证用户名和密码是否正确
Emp emp = empMapper.findByUsername(username);
if(emp == null) {
throw new CustomException("用户名不存在");
}
if(!StrUtil.equals(password, emp.getPassword())) {
throw new CustomException("用户名或密码错误");
}
// 封装并发放Token
Map<String,Object> map = new HashMap<>();
map.put("id", emp.getId());
map.put("username", emp.getUsername());
String token = JwtUtils.generateJwt(map);
return new LoginVO(emp.getId(), emp.getUsername(), emp.getPassword(), token);
}
二.使用令牌验证
1.生成JWT
1.在pom.xml导入依赖
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.引入JwtUtils 并设置"密钥"和"JWT有效期"
public class JwtUtils {
//签名密钥,用于对 JWT 进行签名和验证,在整个应用生命周期内保持不变。
private static final String signKey = "SVRIRUlNQQ==";
//JWT 令牌的过期时间,单位为毫秒,这里设置为 24 小时。
private static final Long expire = 24*60*60*1000L;
//生成加密的JWT的方法___generateJwt
public static String generateJwt(Map<String,Object> claims){
// 使用 Jwts 构建器创建 JWT 令牌
String jwt = Jwts.builder()
// 将传入的 claims 信息添加到 JWT 的负载中
.addClaims(claims)
// 使用 HS256 算法和签名密钥对 JWT 进行签名
.signWith(SignatureAlgorithm.HS256, signKey)
// 设置 JWT 的过期时间,当前时间加上预设的过期时间
.setExpiration(new Date(System.currentTimeMillis() + expire))
// 生成最终的 JWT 令牌字符串
.compact();
//return JWT令牌
return jwt;
}
//生成解密JWT的方法___parseJWT
public static Claims parseJWT(String jwt){
// 使用 Jwts 解析器解析 JWT 令牌
Claims claims = Jwts.parser()
// 设置签名密钥,用于验证 JWT 的签名
.setSigningKey(signKey)
// 解析 JWT 令牌并获取其主体部分
.parseClaimsJws(jwt)
.getBody();
//return 解密得到的信息
return claims;
}
}
三.使用拦截器Interceptor
1.定义TokenInterceptor并在其中重写preHandle方法
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取 JWT Token
String token = request.getHeader("token");
// 如果 Token 为空,说明用户未登录,返回 401 未授权状态码
if (token == null) {
response.setStatus(401);
return false;
}
try {
// 使用 JwtUtils 工具类解析 JWT Token
Claims claims = JwtUtils.parseJWT(token);
// 从解析后的 Claims 中获取用户 ID
Object id = claims.get("id");
// 打印用户 ID
System.out.println(id);
// Token 验证通过,将请求传递给下一个过滤器或目标资源
return true;
} catch (Exception e) {
// Token 解析失败,说明 Token 无效或已过期,返回 401 未授权状态码
response.setStatus(401);
return false;
}
}
}
2.配置拦截器
创建配置类WebConfig,并且实现WebMvcConfigurer接口
@Configuration
public class WebConfig implements WebMvcConfigurer {
//拦截器对象
@Autowired
private TokenInterceptor tokenInterceptor;
/**
* 重写 WebMvcConfigurer 接口的 addInterceptors 方法,用于注册拦截器。
* @param registry 拦截器注册器,通过该对象可以添加自定义拦截器并配置拦截规则
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册自定义的 Token 拦截器对象
registry.addInterceptor(tokenInterceptor)
// 设置拦截器的拦截路径,"/**" 表示拦截所有请求
.addPathPatterns("/**")
// 设置排除拦截的路径,"/login" 路径不会被拦截
.excludePathPatterns("/login");
}
}
关于拦截路径