接到一个需求,某些特定的方法需要指定的用户角色,刚开始想的比较简单,直接在方法中添加几行代码就完事了,后来发现好多方法都有这个功能点,工作量偏大。子曰:多个地方实现同一个功能时,务必封装工具类实现。再然后发现即使封装了工具类,还是会在每个方法中依次调用,不够优雅。故引出了自定义一个注解,只要在方法上添加就可以。
注解的定义比较简单,在这儿我只是给了一个字符串,如果大家角色需求是个 数组的话,同样可以定义成数组的。
1 定义注解
/**
*角色编码权限
*使用时 直接在方法上添加该注解,并且添加角色编码。
* 例 @RoleCodePermission("SADMIN")
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RoleCodePermission {
String value() default "";
}
2 注解解析
/**
*校验操作的方法是否有指定权限
*/
@Aspect
@Component
public class RoleCodePermissionAspect {
private static final Logger logger = LoggerFactory.getLogger(RoleCodePermissionAspect.class);
@Autowired
private ISysUserRoleService userService;
@Pointcut("@annotation(com.nc.common.aspect.annotation.RoleCodePermission)")
public void pt() {
}
/**
* 获取方法上注解的值,
* 根据当前登录用户获取所有的角色编码
* 遍历角色编码,判断方法上注解的值 是否存在集合中
* 如果存在,表示有操作权限 ,不存在表示无权限
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("pt()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
//获取第一个参数
// HttpServletRequest request = pjp.getArgs()[0];
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
RoleCodePermission annotation = method.getAnnotation(RoleCodePermission.class);
// 获取request
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
if (annotation != null) {
//获取注解中的值
String roleColeValue = annotation.value();
if(StringUtils.isBlank(roleColeValue)){
response.sendError(HttpServletResponse.SC_FORBIDDEN,"当前用户无权限操作");
throw new JeecgBootException("当前用户无权限操作");
}
HttpServletResponse response = SpringContextUtils.getHttpServletResponse();
String username = JwtUtil.getUserNameByToken(request);
boolean flag = isContainsRoleCode(roleColeValue, username);
if (!flag) {
logger.info("当前用户无权限操作");
response.sendError(HttpServletResponse.SC_FORBIDDEN,"当前用户无权限操作");
throw new JeecgBootException(sb.toString());
// response.setStatus(HttpServletResponse.SC_FORBIDDEN,"当前用户无权限操作");
}
}
Object result = pjp.proceed();
return result;
}
/**
* 校验当前用户是否包含 指定角色
*
* @param username
* @return
*/
public boolean isContainsRoleCode(String roleColeValue, String username) {
List<String> roleCodeList = userService.queryUserRoleCodeListByUsername(username);
for (int i = 0; i < roleCodeList.size(); i++) {
if (roleCodeList.get(i).equals(roleColeValue)) {
return true;
}
}
return false;
}
}
3 某个导出方法需要特定的角色编码,就可以使用该注解
@AutoLog("导出XXX信息")
@RequestMapping("/batchExport")
@RoleCodePermission("ADMIN")
public ModelAndView batchExport(HttpServletRequest request,HttpServletResponse response) {
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
}