1. 项目环境
后端:SpringBoot
前端:Vue2
框架:若依管理系统
2. 需求
接口对外开放,需要验证访问者身份。
因为若依系统中已经整合了JWT,所以咱们也是用JWT生成token用于身份验证。所有接口使用AOP拦截校验,
3. 生成Token
配置文件,user为访问用户标识,这里写死,也可以做成配置项。
token:
key: 1234567891234567833456
user: 测试用户
public class GenJwtUtil {
/**
* 生成JWT
*/
public static String createJWT(String id, String subject, String key) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key);
return builder.compact();
}
/**
* 解析JWT
*/
public static Claims parseJWT(String jwtStr, String key) {
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}
使用createJWT第一个参数固定写死。
@Value("${token.key}")
private String key;
@Value("${token.user}")
String token = AppJwtUtil.createJWT("999", user, key);
4. 接口使用
@TestAuthentication
@GetMapping("/test")
public AjaxResult test() {
return AjaxResult.success()
}
5. 注解定义
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAuthentication {
}
6. 切面
@Slf4j
@Aspect
@Component
public class TestAuthenticationAspect {
@Value("${token.key}")
private String key;
@Value("${token.user}")
@Around("execution(* com..controller..*.*(..)) " +
"&& @annotation(com.test.common.annotation.TestAuthentication) " +
"&& (@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.GetMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.PostMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.PutMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.PatchMapping))"
)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
try {
HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
String token = request.getHeader("TOKEN");
if (StringUtils.isBlank(token)) {
throw new GlobalException("无权限访问");
}
try {
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
String subject = claims.getSubject();
if (StringUtils.isBlank(subject) || !StringUtils.equals(subject, user)) {
throw new GlobalException("无权限访问");
}
} catch (Exception e) {
throw new GlobalException("解析token失败");
}
return pjp.proceed();
} catch (Throwable e) {
throw e;
}
}
}
至此结束,整个验权流程比较简单,有很大的改进空间,如果项目要求没有那么严格可以使用本方案,也可以在该方案上进行改进,比如生成token时用户数据改为从数据库查询、设置token过期时间等等。