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

来源:互联网 发布:图片对比算法 编辑:程序博客网 时间:2024/06/06 03:58

前言

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

项目源码

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

切面代码

public class PermissionAspect {@Resourceprivate 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")@ResponseBodypublic 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的使用,请见第三篇博客。
原创粉丝点击