jwt令牌有三个部分,第一部分是令牌名,然后数据名,最后加密数据。前两个使用了64个字母代替加密,第三个用算法对前两个就行加密,只有jwt解密算法才能解。
然后登录验证的逻辑是:
如果客户没登陆的情况下访问非login页面,就会强行跳转到登录页面。
登录成功后返回一个加密jwt,前端保存到本地,每次使用add,del,sel时,将数据放在请求头中传到后端。
后端用一个拦截器,login放过,直接去验证登录,其他的路径就验证jwt令牌,没有或者不合法全部拦截下来,返回前端错误提示。
登录代码:
@RequestMapping("/login")
public ReturnData login(String name, String pwd) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", name);
queryWrapper.eq("pwd", pwd);
User user = userMapper.selectOne(queryWrapper);
if (user != null) {
HashMap<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("pwd", pwd);
JwtUtil jwtUtil = new JwtUtil();
String lingpai = jwtUtil.getJwt(map, 12);
return new ReturnData(1, "1", lingpai);
}
return new ReturnData(0, "账户或密码错误", null);
}
过滤器:(过滤会有一个跨域问题,得设置一下)
package com.quxiao.controller;
import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-22 17:20
**/
@Slf4j
@WebFilter(urlPatterns = "/*")
public class CheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域的地址为所有
httpServletResponse.addHeader("Access-Control-Max-Age", "3600"); // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
String tock = httpServletRequest.getHeader("tock");
String s = httpServletRequest.getRequestURL().toString();
//为登录
if (s.contains("login")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
//不为登录,判断令牌
if (tock != null && tock.length() != 0) {
JwtUtil jwtUtil = new JwtUtil();
//判断令牌有安全性
if (jwtUtil.checkJwt(tock)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
log.info("令牌安全性有误");
}
} else {
//无令牌,没登陆
servletResponse.getWriter().write("NOT_LOGIN");
}
}
}
}
拦截器:
package com.quxiao.controller.Interceptor;
import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-23 09:18
**/
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域的地址为所有
httpServletResponse.addHeader("Access-Control-Max-Age", "3600"); // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
String tock = httpServletRequest.getHeader("tock");
String s = httpServletRequest.getRequestURL().toString();
//为登录
if (s.contains("login")) {
return true;
} else {
//不为登录,判断令牌有效性
if (tock != null && tock.length() != 0) {
JwtUtil jwtUtil = new JwtUtil();
//判断令牌有安全性
if (jwtUtil.checkJwt(tock)) {
return true;
} else {
log.info("令牌安全性有误");
}
} else {
//无令牌,没登陆
httpServletResponse.getWriter().write("{\"code\":0,\"msg\":0,\"data\":\"NOT_LOGIN\"}");
}
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("准备返回前端");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("全部完成了");
}
}
将拦截器交给Spring使用管理,加载配置:
package com.quxiao.config;
import com.quxiao.controller.Interceptor.LoginCheckInterceptor;
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;
/**
* @program: SpringBoot4
* @author: quxiao
* @create: 2023-04-23 09:21
**/
//@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
}
过滤器在拦截器前面执行。