通过自定义注解控制权限
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";
}}
推荐阅读
- SpringBoot调用公共模块的自定义注解失效的解决
- python自定义封装带颜色的logging模块
- gitlab|gitlab 通过备份还原 admin/runner 500 Internal Server Error
- 列出所有自定义的function和view
- whlie循环和for循环的应用
- 生活与游戏日记(第182篇)(〔成长瞬间〕关注解决问题2019.10)
- Spring|Spring Boot 自动配置的原理、核心注解以及利用自动配置实现了自定义 Starter 组件
- 自定义MyAdapter
- 如何通过锻炼的方法治疗前列腺肥大
- Android自定义view实现圆环进度条效果