目录
思路
- 前端访问登录接口,登陆成功后,服务端会生成一个JWT令牌,并返回给前端,前端会将JWT令牌保存下来,在同一会话中共享JWT令牌信息,在访问其他功能接口时,前端会在请求头信息中存放JWT令牌信息,请求头的名称为token,过滤器Filter对请求实施统一拦截(登录请求不进行拦截,因为登录成功之后才会生成JWT令牌)并进行登录校验,如果JWT令牌存在并有效,Filter就会放行请求访问Web资源,否则返回错误信息。
登录校验Filter-流程
步骤
- 获取URL
- 判断请求中是否含有login,如果含有,说明是登录操作,放行
- 获取请求头中令牌(token)信息
- 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
- 解析token,如果解析失败,返回错误结果(未登录)
- 放行
流程图
登录校验Filter-代码
过滤器类
java
package com.example.tlias.Filter;
import com.alibaba.fastjson.JSONObject;
import com.example.tlias.pojo.Result;
import com.example.tlias.utils.JwtUtils;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 1.获取请求URL地址
String url = request.getRequestURI().toString();
log.info("获取到的URL地址为:{}", url);
// 2.判断URL是否含有login路径,如果含有,则为登陆操作,放行
if (url.contains("login")) {
log.info("此请求为登陆操作,放行.......");
filterChain.doFilter(request, response);
return; // todo 跳出过滤器
}
// todo 以下是对于不是登录操作的过滤
// 3.获取请求头中的令牌(token)
String token = request.getHeader("token");
// 4.判断是否存在,如果不存在,返回错误结果(未登录)
if (!StringUtils.hasLength(token)) {
log.info("请求头token为空,返回为登录的信息");
Result error = Result.error("NOT_LOGIN"); // 返回的错误信息通过接口文档与前端统一
// todo 手动转换 将对象-->json格式数据===》可以使用阿里巴巴fastJson的工具包,在pom.xml配置文件中添加相关依赖
// todo 控制类返回的对象会自动转换为JSON格式的字符串数据
String noLogin = JSONObject.toJSONString(error);
// 将数据写入响应对象
response.getWriter().write(noLogin);
return; // todo 跳出过滤器
}
// 5.解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(token); // todo 如果解析失败方法就会报错
} catch (Exception e) { // token解析失败
e.printStackTrace();
log.info("解析令牌失败,返回未登录的错误信息");
Result error = Result.error("NOT_LOGIN");
String noLogin = JSONObject.toJSONString(error);
response.getWriter().write(noLogin);
return;
}
// 6.放行
log.info("令牌合法,放行");
filterChain.doFilter(request, response);
}
}
工具类
java
package com.example.tlias.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
private static String signKey = "itheima"; // 设置签名密钥
private static Long expire = 43200000L; // 设置过期时间
/**
* 生成JWT令牌
*
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims) {
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
*
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt) {
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
测试登录
-
使用postman发送请求
*登录接口功能请求
-
登陆成功(返回登录成功信息及令牌信息)
-
登陆失败(返回登录失败信息)
其他接口功能请求
-
未登陆成功访问其他接口功能
-
-
登陆成功访问其他接口
-
前后端联调
Nginx项目压缩包地址如下:
https://hkm-web.oss-cn-beijing.aliyuncs.com/%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3
运行及如果如下:
现在启动项目后会自动跳转到登陆界面,而不是和以前一样直接进入登陆后的界面
成功登录后就可以进入登陆后的界面