《权限系列》----用SpringAop控制权限二

前言

  • 接着上一篇博客说,上一篇文章已经将大部分代码贴出来了,下面该轮到核心代码了,Spring Aop的切面代码。

项目源码

点击这里,到github上下载项目的源码

切面代码

public class PermissionAspect {

@Resource
private CheckAuthorityService checkAuthorityService;

   public void doBefore(JoinPoint jp) throws IOException{
       Method soruceMethod = getSourceMethod(jp);
       if(soruceMethod!=null){
           ValidatePermission oper = soruceMethod.getAnnotation(ValidatePermission.class);
           if (oper != null) {
               String flag= oper.authority();
               Object[] args = jp.getArgs();
               HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
               HttpSession session =request.getSession(); 
               boolean status = checkAuthorityService.checkAccess(flag,session);
               if(status){
                return ;//正常
               }else{
                throw new AccessDeniedException("无权操作该功能!");
               }
           }
       }
}

private Method getSourceMethod(JoinPoint jp){
     Method proxyMethod = ((MethodSignature) jp.getSignature()).getMethod();
      try {
          return jp.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());
      } catch (NoSuchMethodException e) {
          e.printStackTrace();
      } catch (SecurityException e) {
          e.printStackTrace();
      }
      return null;
  }
}
  • 在切面中,我们利用反射,将请求方法上的注解拿到,然后读取此注解中的权限信息,最后将注解信息和session作为参数一块传入到checkAccess()方法中检查权限,下面是要访问的Controller中的方法。

要访问的目标方法

@ValidatePermission(authority="create")
@RequestMapping("/create")
@ResponseBody
public List<String> createUser(){
    userService.addUser(null);
    List<String> list=Arrays.asList("新增用户信息成功");
    return list;
}

检查权限

public class CheckAuthorityServiceImpl implements CheckAuthorityService {

    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private JedisClient jedisClient;

    public Map<String, String> authorityMap = null;

    @Override
    public boolean checkAccess(String flag, HttpSession session) {
        String desUrl="";
        boolean desFlag=false;
        //在session中获取登录名
        String loginName = (String) session.getAttribute("userLoginName");
        //在session中获取用户角色ID
        Integer roleID= (Integer) session.getAttribute("roleID");
        String ROLE_ID_MAP="ROLEID_PERMISSION:"+roleID.toString()+"_"+"MAP";
        //在redis中查找存放资源的map,若map存在,则通过目标资源获取
        authorityMap=jedisClient.hgetAll(ROLE_ID_MAP);
        if (authorityMap!=null && authorityMap.size()>0){
            //匹配资源 这是的时间复杂度大约为O(1)
            desUrl=authorityMap.get(flag);
        }else {
            //若存放资源的map不存在,在数据库中将资源搜出来,放入map中,这时候map的key就是资源(Url)value 是1 目的是省内存
            List<String> list = permissionMapper.getPermissions(loginName);
            if (list != null && list.size() > 0) {
                for (String str : list) {
                    authorityMap.put(str,"1");
                }
                //匹配资源 这是的时间复杂度大约为O(1)
                desUrl=authorityMap.get(flag);
                //将map放入redis中
                jedisClient.hmset(ROLE_ID_MAP,authorityMap);
            }
        }
         //判断资源是否匹配成功
        if (StringUtils.isNoneBlank(desUrl)){
            desFlag=true;
        }
        return desFlag;
    }
}
  • 在小编做的项目中,用户是可以不断增加角色的,也就是说角色是变化的,因为不同的角色对应着不同的资源,所以在检查用户权限的时候,小编将资源信息存入一个HashMap中,然后叫此HashMap放入Redis中,当每次判断权限时,我们根据用户的角色ID将map从redis中取出来,然后根据目标资源去map中get(),这样以来,get()的时间复杂度是O(1),提高效率。

小结

  • 置于redis的使用,请见第三篇博客。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值