通过自定义注解控制权限

1、编写自定义注解类

/** * 自定义Access注解 * 若使用在类上,这个类的所有方法都进行权限校验,暂不支持 * 若使用在方法上,这个方法进行权限校验 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Access {/** * 表明该方法允许哪些角色id访问 * @return */ RoleEnum[] roles() default {}; /** * 备注 */ String comment(); }

2、定义枚举值
/** * 角色枚举类 */ public enum RoleEnum {C2C_SELLER(1,"C2C商家"), CSR(2,"客服"), FINANCE_ADMIN(5,"财务"), SUPER_ADMIN(7,"超级管理员"), EM_ADMIN(10,"电商管理员"), KOL_ADMIN(25,"市场运营"), UNKNOWN(-100,"未知角色"), BRAND_SELLER(100,"供应商"), ; RoleEnum(Integer roleId, String desc) { this.roleId = roleId; this.desc = desc; }/** * 角色ID */ private Integer roleId; /** * 角色描述 */ private String desc; public Integer getRoleId() { return roleId; }public void setRoleId(Integer roleId) { this.roleId = roleId; }public String getDesc() { return desc; }public void setDesc(String desc) { this.desc = desc; }@Override public String toString() { return "RoleEnum{" + "roleId=" + roleId + ", desc='" + desc + '\'' + '}'; } }

【通过自定义注解控制权限】3、通过面向切面编程进行权限控制
/** * 拦截使用了@Access注解的业务方法 * * 根据@Access的配置来确定可访问该方法的角色 * * 以后可以以一个uri为一个权限单元,可以为角色分配多个权限单元 * * 这里会直接根据url去查这个角色有没有对应的权限,有:放行,没有:提示无权限 * */ @Component @Aspect public class AccessInterceptor {private static final Logger LOGGER = LoggerFactory.getLogger(AccessInterceptor.class); //@Resource //private AppEnvironment appEnvironment; // //@Resource //private BackendUserMapper backendUserMapper; // //@Resource //private BackendRoleMapper backendRoleMapper; @SuppressWarnings("unused") @Around("@annotation(access)") public Object doAround(ProceedingJoinPoint pjp, Access access) throws Throwable { //获取请求上下文 RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); //获取请求相关信息,暂时没用 String url = request.getRequestURL().toString(); String method = request.getMethod(); String uri = request.getRequestURI(); String queryString = request.getQueryString(); if (LOGGER.isDebugEnabled()) { LOGGER.debug(url); } //开发环境跳过权限控制 //if (appEnvironment.isDev()) { //return pjp.proceed(); //} if (!UserUtil.isInternalRole()) { //外部权限校验access标签校验权限 verifyUserPrivileges(access.roles()); } //继续执行 return pjp.proceed(); }/** * 校验用户权限 * 目前系统只需要user的角色id和roles里的角色id一直就算通过校验 * * @param roles */ private void verifyUserPrivileges(RoleEnum[] roles) { //获得用户的角色ID Subject subject = SecurityUtils.getSubject(); UserPrincipal userPrincipal = (UserPrincipal) subject.getPrincipal(); if (userPrincipal == null) { throw new BizException(ErrorCodeEnum.LOGIN_FAILED); } else {//校验权限 //该用户的角色为空,默认没有权限,校验不通过 if (userPrincipal.getRoleEnum() == null) { throw new BizException(ErrorCodeEnum.ACCESS_FAILED); } RoleEnum userRole = userPrincipal.getRoleEnum(); List roleEnumList = Arrays.asList(roles); if (roleEnumList.contains(userRole)) { return; } else { throw new BizException(ErrorCodeEnum.ACCESS_FAILED); } } } }


4、获取用户权限类型
/** * 用户工具类 */ public class UserUtil { private static Logger logger = LoggerFactory.getLogger(UserUtil.class); /** * 内部权限 * @return */ public static boolean isInternalRole() { Subject subject = SecurityUtils.getSubject(); UserPrincipal principal = (UserPrincipal)subject.getPrincipal(); RoleEnum role = principal.getRoleEnum(); return role == RoleEnum.SUPER_ADMIN || role == RoleEnum.EM_ADMIN || role == RoleEnum.FINANCE_ADMIN ; }}


5、使用案例
@RestController @RequestMapping(value = "https://www.it610.com/test") public class TestAccessController {@Access(comment = "仅限内部角色访问", roles = {RoleEnum.SUPER_ADMIN, RoleEnum.EM_ADMIN}) @PostMapping("/access") public JsonResult testAccess() { return "access success"; }}


    推荐阅读