在Web应用程序中,注解是一种方便的方式来拦截和处理请求。可以通过在代码中添加注解来定义一些特殊的行为,比如拦截器(Interceptor)等。
拦截器是一种处理请求的技术,它可以在请求被处理之前或之后对请求进行处理。通过使用拦截器,可以在处理请求之前或之后添加额外的逻辑,例如身份验证、权限检查等。
所需JWT依赖:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
定义一个登录用户类:
/**
* @Author RainCity
* @Date 2021-05-24 10:49:59
* @Desc 登录用户
*/
public class LoginUser implements Serializable {
private static final long serialVersionUID = 768788313972112861L;
/**登录名*/
private String loginName;
/**登录密码*/
private String password;
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "LoginUser {" +
"loginName='" + loginName + '\'' +
", password='" + password + '\'' +
'}';
}
}
利用JWT生成token:
/**
* @Author RainCity
* @Date 2021-05-24 11:47:04
* @Desc jwt 根据当前登录人生成token
*/
public class JsonWebToken {
private static final String ISSUER="ISSUER";
/**
* 生成token---有过期时间
* @param loginName 登录名(唯一标识)
* @param password 登陆密码
* @param second 多少秒后过期
* @return {@link String}
* @version v1.0.0
*/
public static String createToken(String loginName, String password, int second) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, second);
return JWT.create()
.withJWTId("jwt_id")
//签发者
.withIssuer(ISSUER)
//将 登录名 保存到token里面
.withAudience(loginName)
//签发时间
.withIssuedAt(new Date())
//过期时间
.withExpiresAt(cal.getTime())
//以 password 作为token的密钥
.sign(Algorithm.HMAC256(password));
}
/**
* 生成token---无过期时间
* @param loginName 登录名(唯一标识)
* @param password 登陆密码
* @return {@link String}
* @version v1.0.0
*/
public static String createToken(String loginName, String password) {
return JWT.create()
.withJWTId("jwt_id")
//签发者
.withIssuer(ISSUER)
//将 登录名 保存到token里面
.withAudience(loginName)
//签发时间
.withIssuedAt(new Date())
//过期时间
//.withExpiresAt(cal.getTime())
//以 loginName+password 作为token的密钥
.sign(Algorithm.HMAC256(loginName+password));
}
}
注解:
/**
* @Author RainCity
* @Date 2021-05-24 10:25:39
* @Desc 在需要验证的方法上使用此注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthRequired {
boolean required() default true;
}
请求拦截器:
/**
* @Author RainCity
* @Date 2021-05-24 10:39:24
* @Desc
*/
@SuppressWarnings(value = {"rawtypes" })
public class AuthenticationInterceptor implements AsyncHandlerInterceptor {
@Resource
public RedisTemplate redisTemplate;
private static final String INVALID_MSG ="登录失效,请重新登录";
private static final String NOT_EXIST_MSG ="用户不存在,请重新登录";
private static final String LOGIN_KEY = "CUS_LOGIN:";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 判断接口是否需要登录
AuthRequired methodAnnotation = method.getAnnotation(AuthRequired.class);
// 有 @AuthRequired 注解,需要认证
if(null != methodAnnotation){
// 执行认证
// 从 http 请求头中取出 token
String token = request.getHeader("token");
Assert.notNull(token, "未登录");
String loginName;
try {
// 获取 token 中的 账号
loginName = JWT.decode(token).getAudience().get(0);
if(StringUtils.isEmpty(loginName)){
throw new RuntimeException(INVALID_MSG);
}
LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(LOGIN_KEY + loginName);
if (null == loginUser) {
throw new RuntimeException(NOT_EXIST_MSG);
}
// 验证 token
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(loginUser.getLoginName()+loginUser.getPassword())).build();
verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
throw new RuntimeException("身份认证失败");
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
}
}
注解拦截请求是一种优雅而灵活的方式,可以帮助我们更好地管理和处理请求。