在开发登录接口时你都需要做什么,不会就是简单的将数据和后端数据对比吧,都对的话就进入没有就拒绝访问,那样的话是不是在忽悠小孩子呀~~~~~哈哈哈
话不多说,开搞
一、登录接口编写
登录接口的参数校验和注册接口一样,可以看看上一篇注册接口文章,对啦还有Md5的加密欧
// 登录接口 @PostMapping("/login") public Result login(@Pattern(regexp = "^\\d{4,6}$") String username,@Pattern(regexp = "^[a-zA-Z]\\w{5,17}$") String password){ // 根据用户名查询用户 User LoginUser = userService.select(username); // 判断用户是否存在 if(LoginUser == null){ return Result.error("没有该账户"); } // 判断密码是否正确 loginUser 对象中的password是密文 if(Md5Util.getMD5String(password).equals(LoginUser.getPassword())){ // 这里用来生成token } return Result.error("密码错误"); }
二、 导入JWT
1.导入JWT依赖
<!-- 生成令牌jwt依赖--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>4.4.0</version> </dependency>
2.封装JWT工具类
public class JwtUtil { private static final String KEY = "yangyangshije"; //接收业务数据,生成token并返回 public static String genToken(Map<String, Object> claims) { return JWT.create() .withClaim("claims", claims) .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12)) .sign(Algorithm.HMAC256(KEY)); } //接收token,验证token,并返回业务数据 public static Map<String, Object> parseToken(String token) { return JWT.require(Algorithm.HMAC256(KEY)) .build() .verify(token) .getClaim("claims") .asMap(); } }
3.导入登入接口生成Token
// 登录接口 @PostMapping("/login") public Result login(@Pattern(regexp = "^\\d{4,6}$") String username,@Pattern(regexp = "^[a-zA-Z]\\w{5,17}$") String password){ // 根据用户名查询用户 User LoginUser = userService.select(username); // 判断用户是否存在 if(LoginUser == null){ return Result.error("没有该账户"); } // 判断密码是否正确 loginUser 对象中的password是密文 if(Md5Util.getMD5String(password).equals(LoginUser.getPassword())){ // 这里用来生成token // 登陆成功生成一个token 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); // jwt token令牌发布 登陆验证 } return Result.error("密码错误"); }
三、拦截器
1.生成拦截器
// 拦截器 @Component // 拦截器对象注入 public class LoginInterceptor implements HandlerInterceptor { @Override //Override是伪代码,判断所有父类是否有错误 // preHandle 调用时间:controller方法处理之前 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ // 令牌验证 请求头名字 String token = request.getHeader("Authorization"); // 验证token try { Map<String, Object> claims = JwtUtil.parseToken(token); // 把业务数据存储到ThreadLocal ThreadLocalUtil.set(claims); // 解析成功应该是放行 return true; }catch(Exception e){ // http响应状态码401 response.setStatus(401); // 不放行 return false; } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); // 清空theradLocal中的数据 ThreadLocalUtil.remove(); } }
/** * ThreadLocal 工具类 提供线程的局部变量,用来存储数据: set()/get() 使用threadlocal存储的数据,线程安全 */ @SuppressWarnings("all") public class ThreadLocalUtil { //提供ThreadLocal对象, private static final ThreadLocal THREAD_LOCAL = new ThreadLocal(); //根据键获取值 public static <T> T get(){ return (T) THREAD_LOCAL.get(); } //存储键值对 public static void set(Object value){ THREAD_LOCAL.set(value); } //清除ThreadLocal 防止内存泄漏 public static void remove(){ THREAD_LOCAL.remove(); } }
2.注入拦截器
import org.example.interceptor.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 public class WebConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; // 快捷建立 addinter @Override public void addInterceptors(InterceptorRegistry registry) { // 拦截器的注册和使用不能将所有请求数据都拦截 // 登录和注册接口不拦截 registry.addInterceptor(loginInterceptor).excludePathPatterns("/login","/add"); } }
四、测试
1.错误测试
2.正确测试
登录
删除