今天复习,重做一遍后端项目,但是登录的时候总是获取不到token值,百思不得其解,原因竟然只是一个"/"路径问题,
在excludePathPatterns("/user/register","/user/login")中的参数最前面一定要带"/",否则找不到此路径,到拦截器里面token的值为null,就会捕获异常然后将状态设置为401
正确写法:excludePathPatterns("/user/register","/user/login")
错误写法:excludePathPatterns("user/register","user/login")
这仅仅是我的token为空的问题,如果大家还有其他token为空的问题,可以一起探讨
问题如下:
自定义拦截器如下
package com.example.interceptors;
import com.example.utils.JwtUtil;
import com.example.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Map;
/*
* 拦截器
* */
/*将此类加入ioc容器*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
try {
Map<String, Object> claims = JwtUtil.parseToken(token);
//将token放到ThreadLocal里面
ThreadLocalUtil.set(claims);
return true;
} catch (Exception e) {
e.printStackTrace();
response.setStatus(401);
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ThreadLocalUtil.remove();
}
}
配置类如下
package com.example.config;
import com.example.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/*配置类*/
//@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器
@Configuration
//WebMvcConfigurer就是一个接口里面写了一些默认方法,常用的就是addInterceptors添加拦截器
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*token值为空的原因是在excludePathPatterns中的路径user前面没有加/,所以访问不到此路径*/
registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/register","/user/login");
}
}
controller:
package com.example.controller;
import com.example.pojo.Result;
import com.example.pojo.User;
import com.example.service.UserService;
import com.example.utils.JwtUtil;
import com.example.utils.Md5Util;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@Validated
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("register")
public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
//先使用username查询数据库中是否有该用户,如果没有就注册,如果有就反馈错误信息
User u = userService.findByUsername(username);
if (u == null) {
//注册
userService.register(username, password);
return Result.success();
} else {
return Result.error("操作失败");
}
}
// 登录接口
@PostMapping("/login")
public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
/*使用*/
User loginUser = userService.findByUsername(username);
/*如果username不存在的话就返回用户错误信息*/
if (loginUser == null) {
return Result.error("用户名错误");
}
//使用加密的密码与数据库中加密的密码进行比较
if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
//登录成功
//登录校验
Map<String, Object> claims = new HashMap<>();
claims.put("id", loginUser.getId());
claims.put("username", loginUser.getUsername());
String token = JwtUtil.genToken(claims);
return Result.success(token);
} else {
return Result.error("密码错误");
}
}
}