Jwt,过滤器,拦截器
JWT
JWT JSON Web Token,是一种用户身份识别的令牌技术。用于解决web开发中身份识别问题。
JWT主要由三部分组成:header头,body 载荷,Signature签名
header:主要存放令牌的签名算法和类型
body:存放一些数据,比如用户的身份信息
signature:header+body+密钥通过签名算法生成的签名字符串,用于验证身份信息,和权限校验.
要使用jwt首先要引入对应的依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
public class JwtDemo {
public static void main(String[] args) throws InterruptedException {
//1. 生成JWT令牌
//1.1 准备载荷信息,即用户的身份信息
Map<String, Object> claims = new HashMap<>();
claims.put("id", 1);
claims.put("username", "tom");
//1.2 生成JWT令牌
String token = Jwts.builder()
//把载荷内容设置到JWT令牌里
.setClaims(claims)
//设置令牌的过期时间。这里设置有效期为:截止到当前时间+1000毫秒,即有效期只有1秒(可以根据实际情况自定义有效期)
.setExpiration(new Date(System.currentTimeMillis() + 1000))
//设置令牌的密钥。在将来解析令牌时,根据密钥校验令牌的签名,防止令牌被篡改
.signWith(SignatureAlgorithm.HS256, "itheima")
//生成令牌
.compact();
System.out.println("token =" + token);
//2. 校验与解析令牌:如果令牌过期,会抛出异常;如果令牌被篡改,会抛出异常;如果一切正常,会得到令牌里的载荷内容
Claims claimsRes = Jwts.parser()
//设置密钥。用于稍后的令牌签名校验,判断令牌是否被篡改了。如果令牌被篡改,会抛出异常
.setSigningKey("itheima")
//校验并解析令牌。如果令牌被篡改或已过期,会抛出异常
.parseClaimsJws(token)
//获取令牌载荷内容
.getBody();
System.out.println(claimsRes);
}
}
一般,我们会在登录的接口中设置jwt令牌,通过定义一个claims对象,调用JwtUtil类下的createJWT()方法来创建出一个token字段
/**
* 员工登录
*/
@Override
public Result<EmployeeLoginVO> login(EmployeeLoginDTO employeeLoginDTO) {
String username = employeeLoginDTO.getUsername();
String password = employeeLoginDTO.getPassword();
//校验参数
if (StringUtils.isAnyBlank(username, password)) {
//账号密码错误
throw new ParameterIsNullException(MessageConstant.PARAMETER_IS_NULL);
}
//1、根据用户名查询数据库中的数据
Employee employee = employeeMapper.getByUsername(username); //
//2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
if (employee == null) {
//账号不存在
throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
}
//密码比对
password = DigestUtils.md5DigestAsHex(password.getBytes());
if (!password.equals(employee.getPassword())) {
//密码错误
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
if (StatusConstant.DISABLE.equals(employee.getStatus())) {
//账号被锁定
throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
}
//3、返回EmployeeLoginVO实体对象
//登录成功后,生成jwt令牌
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
String token = JwtUtil.createJWT(
jwtProperties.getAdminSecretKey(),
jwtProperties.getAdminTtl(),
claims);
EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
.id(employee.getId())
.userName(employee.getUsername())
.name(employee.getName())
.token(token)
.build();
return Result.success(employeeLoginVO);
}
过滤器Filter
过滤器Filter是基于Servlet规范的,对所有请求/响应进行全局处理,一般通过实现Filter接口,然后重写doFilter()方法来实现业务需求.
Filter是 JavaEE的技术,doFilter()方法总共有三个参数:request response chain
request 代表请求的Request对象,在接收数据时一般会强转成HttpServletRequest对象来使用
response 代表Response 响应对象
chain 代表过滤器链对象,调用doFilter表示放行
Filter一般还要搭配@WebFilter注解来设置拦截请求的范围
@WebFilter("拦截范围")
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (httpRequest.getSession().getAttribute("user") == null) {
((HttpServletResponse) response).sendRedirect("/login");
return;
}
chain.doFilter(request, response);
}
}
拦截器
拦截器是由SpringMVC框架提供的技术,能够针对特定请求(如Controller方法)进行拦截
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getSession().getAttribute("user") == null) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "未登录");
return false; // 中断请求
}
return true; // 继续执行
}
}
在使用拦截器时,一般需要在WebConfig 类中配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/**") // 拦截路径
.excludePathPatterns("/public/**"); // 排除路径
}
}