2.权限模块
原理:自定义一个权限注解接口,每个对外提供的请求接口配置好权限注解及权限代码,拦截器配置好拦截请求后,会获取每个接口方法上的权限注解的代码,在自定义方法进行相对应的权限判断
如:先从redis中查询用户的角色,判断对应角色是否拥有这个代码权限,数据库需要用户表、角色表、页面权限表、关系关联表
2.1在每个需要权限控制的接口上添加自定义注解,配置权限代码
图片.png
2.2自定义权限注解
package com.lozinn.system.annotation;
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)
public @interface PermissionCode {
//页面代码
long pageCode() default 0;
//页面授权代码
long actionCode() default 0;
}
2.3拦截类配置
package com.lozinn.common.config;
import com.lozinn.common.interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截配置类
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
AuthenticationInterceptor AuthenticationInterceptor(){
return new AuthenticationInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry){
//addPathPatterns设置拦截/**所有请求,同时excludePathPatterns排除指定
registry.addInterceptor(AuthenticationInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/error")
//.excludePathPatterns("/user/addUser")
.excludePathPatterns("/user/userLogin")
.excludePathPatterns("/swagger-ui.html");
}
}
2.4配置身份验证的拦截器
package com.lozinn.common.interceptor;
import com.alibaba.druid.util.StringUtils;
import com.lozinn.common.util.JWTUtils;
import com.lozinn.system.annotation.PermissionCode;
import com.lozinn.system.exception.MyException;
import com.lozinn.system.exception.TokenException;
import com.lozinn.system.myenum.ExceptionCodeEnum;
import com.lozinn.system.service.PermissionService;
import com.lozinn.system.util.UserThreadLocal;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* 身份验证拦截器
*/
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
PermissionService permissionService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//权限拦截验证
String url = request.getRequestURI();
String token = request.getHeader("Authorization");
if(StringUtils.isEmpty(token)){
throw new TokenException();
}
String userId = null;
try{
//校验token并获取userId
userId = JWTUtils.getUserIdFromToken(token);
}catch (Exception e){
if(e instanceof ExpiredJwtException){
log.info("token ExpiredJwtException:"+ExceptionCodeEnum.TOKEN_EXPIRED_ERROR.getMsg());
throw new MyException(ExceptionCodeEnum.TOKEN_EXPIRED_ERROR);
}else if(e instanceof SignatureException){
log.info("token SignatureException:"+ExceptionCodeEnum.TOKEN_CHECK_FAIL.getMsg());
throw new MyException(ExceptionCodeEnum.TOKEN_CHECK_FAIL);
}else if(e instanceof MalformedJwtException){
log.info("token MalformedJwtException:"+ExceptionCodeEnum.MALFORMEDJWT_ERROR.getMsg());
throw new MyException(ExceptionCodeEnum.MALFORMEDJWT_ERROR);
}
}
//线程保存userId,afterCompletion注销userId,使userId只在请求过程中可用
UserThreadLocal.setUserId(Long.parseLong(userId));
//校验用户权限
if(handler instanceof HandlerMethod){
HandlerMethod hm = (HandlerMethod) handler;
Class<?> clazz = hm.getBeanType();
Method m = hm.getMethod();
if(m != null && m.isAnnotationPresent(PermissionCode.class)){
PermissionCode permissionCode = m.getAnnotation(PermissionCode.class);
log.info("------>userId:"+userId+",access Method name-->:"+m.getName()+",pageCode:"+permissionCode.pageCode()+",actionCode:"+permissionCode.actionCode());
//这里是具体的权限业务控制,可自行定义,一般是根据userId获取角色并判断是否拥有pageCode和actionCode
permissionService.getUserPermission(userId,permissionCode.pageCode(),permissionCode.actionCode());
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
UserThreadLocal.setUserId(null);
}
}