文章目录
- 一、简要概述
- 二、实现过程
- 1. pom引入依赖
- 2. 自定义注解
- 3. 定义切面
- 4. 定义权限检查逻辑
- 三、注解使用
- 四、运行结果
- 五、源码放送
一、简要概述
Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。我们借助expireAfterWrite
过期时间设置和springboot的自定义注解、切面等技术来打造最简单的接口鉴权系统。
二、实现过程
1. pom引入依赖
在原有springboot基础上引入切面、guava依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.2-jre</version></dependency>
2. 自定义注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthToken
{}
3. 定义切面
在aop的逻辑内,先走@Around注解的方法。然后是@Before注解的方法,然后这两个都通过了,走核心代码,核心代码走完,无论核心有没有返回值,都会走@After方法。然后如果程序无异常,正常返回就走@AfterReturn,有异常就走@AfterThrowing。
我们这里使用了 @Before:前置通知,在调用目标方法之前执行检查
import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import com.fly.core.exception.ValidateException;
import com.fly.core.utils.HttpServletUtils;
import com.fly.demo.aspect.annotation.AuthToken;
import com.fly.demo.service.TokenService;import lombok.extern.slf4j.Slf4j;@Slf4j
@Aspect
@Order(0)
@Component
public class AuthTokenAspect
{@AutowiredTokenService tokenService;/*** 使用AuthToken注解标注的类* */@Before("@annotation(authToken)")public void doBefore(JoinPoint joinPoint, AuthToken authToken){HttpServletRequest request = HttpServletUtils.getRequest();if (request == null){log.error("AuthToken注解使用错误,当前请求非web请求");}log.info("开始执行鉴权检查");String token = request.getHeader("token");if (!tokenService.valide(token)){throw new ValidateException("对不起,您无权访问该接口,请检查token参数");}}
}
4. 定义权限检查逻辑
import java.util.UUID;
import java.util.concurrent.TimeUnit;import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;import lombok.extern.slf4j.Slf4j;@Slf4j
@Service
public class TokenService
{/*** 30分钟失效*/Cache<String, String> cache = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).build();/*** 验证token是否合法* * @param token*/public boolean valide(String token){return StringUtils.equals(token, getToken());}/*** 获取sysToken*/private String getToken(){String sysToken = cache.getIfPresent("token");if (sysToken == null){sysToken = UUID.randomUUID().toString().replace("-", "");log.info("------ now valid sysToken is: {}", sysToken);cache.put("token", sysToken);}return sysToken;}
}
三、注解使用
我们在需要执行权限检查的地方添加@AuthToken
即可
@AuthToken@ApiOperation("刷新欢迎语")@PostMapping("/refresh")@ApiImplicitParam(name = "message", value = "欢迎语", allowableValues = "骝马新跨白玉鞍,战罢沙场月色寒。城头铁鼓声犹震,匣里金刀血未干。,活捉洪真英,生擒李知恩! ", required = true)public JsonResult<?> refresh(@RequestHeader String token, String message){if (StringUtils.isBlank(message)){return JsonResult.error("message不能为空");}boolean success = updateWelcomeMsg(message) > 0;return success ? JsonResult.success(message) : JsonResult.error("刷新欢迎语失败");}
四、运行结果
token不合法提示
后台查看token
请求头填入合法token
接口调用成功
五、源码放送
https://gitcode.com/00fly/springboot-demo/overview
有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!
-over-