|
@@ -0,0 +1,151 @@
|
|
|
+package boot.common.interceptor;
|
|
|
+
|
|
|
+import boot.common.bean.LocalUser;
|
|
|
+import boot.common.constant.SchoolConstant;
|
|
|
+import boot.common.respond.ApiCode;
|
|
|
+import boot.common.respond.UnAuthenticatedException;
|
|
|
+import boot.common.utils.JwtToken;
|
|
|
+import boot.common.utils.RedisUtils;
|
|
|
+import boot.modules.manage.pojo.Manage;
|
|
|
+import boot.modules.manage.service.ManageService;
|
|
|
+import boot.modules.user.pojo.User;
|
|
|
+import boot.modules.user.service.UserService;
|
|
|
+import com.auth0.jwt.interfaces.Claim;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.method.HandlerMethod;
|
|
|
+import org.springframework.web.servlet.ModelAndView;
|
|
|
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Optional;
|
|
|
+
|
|
|
+public class ManagePermissionInterceptor extends HandlerInterceptorAdapter {
|
|
|
+ @Autowired
|
|
|
+ private UserService userService;
|
|
|
+ @Autowired
|
|
|
+ private RedisUtils redisUtils;
|
|
|
+ @Autowired
|
|
|
+ private ManageService manageService;
|
|
|
+
|
|
|
+ public ManagePermissionInterceptor() {
|
|
|
+ super();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
|
|
+ Optional<ManageCheck> authCheck = this.getAuthCheck(handler);
|
|
|
+ //如果没有在方法(接口方法上)上注释 @AuthCheck 就会直接放行,不进行权限检查
|
|
|
+ if (!authCheck.isPresent()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取请求头中的 Token,没有就抛异常 “401, "非法访问"
|
|
|
+ String bearerToken = request.getHeader("Authorization");
|
|
|
+ if (StringUtils.isEmpty(bearerToken)) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.UNAUTHORIZED);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!bearerToken.startsWith("Bearer")) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.UNAUTHORIZED);
|
|
|
+ }
|
|
|
+ //根据Token以空格来进行分离 Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInVOYW1lIjoiMTM0MTExMTExMTEiLCJzY29wZSI6OCwiZXhwIjoxNzg5MjY5MDI2LCJpYXQiOjE3MDI4NjkwMjZ9.brwajljjhr4LYi9kh9lDKvtQsbfrFaDU30lYx5Min9Y
|
|
|
+ String[] tokens = bearerToken.split(" ");
|
|
|
+ if (!(tokens.length == 2)) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.UNAUTHORIZED);
|
|
|
+ }
|
|
|
+ //分离后的数组第一个是 Bearer,第二个是该用户的 Token
|
|
|
+ String token = tokens[1];
|
|
|
+
|
|
|
+ //用于验证并提取JWT中的声明(Claims)
|
|
|
+ Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
|
|
|
+ //获取每一个值 如果为空直接抛异常
|
|
|
+ Map<String, Claim> map = optionalMap
|
|
|
+ .orElseThrow(() -> new UnAuthenticatedException(ApiCode.UNAUTHORIZED));
|
|
|
+
|
|
|
+ String username = map.get("uName").asString();
|
|
|
+
|
|
|
+ //检测用户是否被踢出
|
|
|
+ if (redisUtils.get(SchoolConstant.SCHOOL_LOGIN_USER + username + ":" + token) == null) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.UNAUTHORIZED);
|
|
|
+ }
|
|
|
+ //
|
|
|
+ boolean valid = this.hasPermission(authCheck.get(), map);
|
|
|
+ if (valid) {
|
|
|
+ this.setToThreadLocal(map);
|
|
|
+ }
|
|
|
+ return valid;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 如果权限验证通过的情况下 将相关信息存储在线程本地
|
|
|
+ *
|
|
|
+ * @param map
|
|
|
+ */
|
|
|
+ private void setToThreadLocal(Map<String, Claim> map) {
|
|
|
+ Integer uid = map.get("uid").asInt();
|
|
|
+ Integer scope = map.get("scope").asInt();
|
|
|
+ User user = userService.getById(uid);
|
|
|
+ if (user == null) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.NOT_PERMISSION);
|
|
|
+ }
|
|
|
+ LocalUser.set(user, scope);
|
|
|
+// System.out.println(LocalUser.getUser());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证传入的权限级别是否与 "scope" 的值匹配
|
|
|
+ *
|
|
|
+ * @param authCheck
|
|
|
+ * @param map
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean hasPermission(ManageCheck authCheck, Map<String, Claim> map) {
|
|
|
+ //获取注解上的 value 值
|
|
|
+ Integer level = authCheck.value();
|
|
|
+ Integer scope = map.get("scope").asInt();
|
|
|
+ if (level > scope) {
|
|
|
+ throw new UnAuthenticatedException(ApiCode.NOT_PERMISSION);
|
|
|
+ }
|
|
|
+
|
|
|
+ LambdaQueryWrapper<Manage> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ Long uid = map.get("uid").asLong();
|
|
|
+
|
|
|
+ wrapper.eq(Manage::getId,uid);
|
|
|
+
|
|
|
+ Manage manage = manageService.getById(uid);
|
|
|
+ if (manage==null){
|
|
|
+ throw new UnAuthenticatedException(ApiCode.NOT_PERMISSION);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
|
|
+ super.postHandle(request, response, handler, modelAndView);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
|
|
+ LocalUser.clear();
|
|
|
+ super.afterCompletion(request, response, handler, ex);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Optional<ManageCheck> getAuthCheck(Object handler) {
|
|
|
+ //先检查它的类型,以确保安全地访问其属性或方法。
|
|
|
+ if (handler instanceof HandlerMethod) {
|
|
|
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
|
|
|
+ // 获取方法上的注解信息 是否添加了 @AuthCheck 注解
|
|
|
+ ManageCheck authCheck = handlerMethod.getMethod().getAnnotation(ManageCheck.class);
|
|
|
+ if (authCheck == null) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ return Optional.of(authCheck);
|
|
|
+ }
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|