spring aop实现用户权限管理的示例

 更新时间:2017年12月07日 09:15:54   作者:whfstudio  
本篇文章主要介绍了spring aop实现用户权限管理的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

AOP 在实际项目中运用的场景主要有 权限管理(Authority Management)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging) 等。

问题源于项目开发

最近项目中需要做一个权限管理模块,按照之前同事的做法是在controller层的每个接口调用之前上做逻辑判断,这样做也没有不妥,但是代码重复率太高,而且是体力劳动,so,便有了如题所说的使用spring aop做一个切点来实现通用功能的权限管理,这样也就降低了项目后期开发的可扩展性。

权限管理的代码实现与配置文件

在最小的代码修改程度上,aop无疑是最理想的选择。项目中有各种权限的复合,相对来说逻辑复杂度比较高,所以一步步来。因为权限涉及到的是后端接口的调用所以楼主选择在controller层代码做切面,而切点就是controller中的各个方法块,对于通用访问权限,我们使用execution表达式进行排除。

只读管理员权限的实现及切点选择

对于实现排除通用的controller,楼主采用的是execution表达式逻辑运算。因为只读管理员拥有全局读权限,而对于增删改权限,楼主采用的是使用切点切入是增删改的方法,so,这个时候规范的方法命名就很重要了。对于各种与只读管理员进行复合的各种管理员,我们在代码中做一下特殊判断即可。下面是spring aop的配置文件配置方法。

<bean id="usersPermissionsAdvice"
     class="com.thundersoft.metadata.aop.UsersPermissionsAdvice"/>
  <aop:config>
    <!--定义切面 -->
    <aop:aspect id="authAspect" ref="usersPermissionsAdvice">
      <!-- 定义切入点 (配置在com.thundersoft.metadata.web.controller下所有的类在调用之前都会被拦截) -->
      <aop:pointcut
          expression="(execution(* com.thundersoft.metadata.web.controller.*.add*(..)) or
          execution(* com.thundersoft.metadata.web.controller.*.edit*(..)) or
          execution(* com.thundersoft.metadata.web.controller.*.del*(..)) or
          execution(* com.thundersoft.metadata.web.controller.*.update*(..)) or
          execution(* com.thundersoft.metadata.web.controller.*.insert*(..)) or
          execution(* com.thundersoft.metadata.web.controller.*.modif*(..))) or
          execution(* com.thundersoft.metadata.web.controller.*.down*(..))) and (
          !execution(* com.thundersoft.metadata.web.controller.FindPasswordController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.SelfServiceController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.HomeController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.UserStatusController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.DashboardController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.MainController.*(..))))"
          id="authPointCut"/>
      <!--方法被调用之前执行的 -->
      <aop:before method="readOnly"
            pointcut-ref="authPointCut"/>
    </aop:aspect>
  </aop:config>

只读管理员权限管理代码实现

上面说了那么多,废话不多说了,下面是对只读权限与各种复合权限进行控制的切面代码实现。

/**
   * 对只读管理员以及其复合管理员进行aop拦截判断.
   * @param joinPoint 切入点.
   * @throws IOException
   */
  public void readOnly(JoinPoint joinPoint) throws IOException {

    /**
     * 获取被拦截的方法.
     */
    String methodName = joinPoint.getSignature().getName();

    /**
     * 获取被拦截的对象.
     */
    Object object = joinPoint.getTarget();
    logger.info("权限管理aop,方法名称" + methodName);
    HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    String roleFlag = GetLoginUserInfor.getLoginUserRole(request);

    /**
     * 超级管理员
     */
    if (PermissionsLabeled.super_Admin.equals(roleFlag)) {
      return;
    }

    /**
     * 只读管理员做数据更改权限的判断
     */
    if (PermissionsLabeled.reader_Admin.equals(roleFlag)) {
      logger.error("只读管理员无操作权限!");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    }

    /**
     * 部门管理员,且为只读管理员,
     */
    if (PermissionsLabeled.dept_reader_Admin.equals(roleFlag)) {
      if (object instanceof DepartmentController) {
        return;
      }
      if (object instanceof UserController) {
        if (methodName.contains("addAdmin")) {
          response.sendRedirect(request.getContextPath() + "/auth/readOnly");
        }
        if (methodName.contains("deleteAdmin")) {
          response.sendRedirect(request.getContextPath() + "/auth/readOnly");
        }
        if (methodName.contains("updateAdmin")) {
          response.sendRedirect(request.getContextPath() + "/auth/readOnly");
        }
        return;
      }
      if (object instanceof GroupController) {
        return;
      }
      logger.error("部门管理员,且为只读管理员无操作权限!");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    }

    /**
     * 应用管理员,且为只读管理员
     */
    if (PermissionsLabeled.app_reader_Admin.equals(roleFlag)) {
      if (object instanceof AppController) {
        return;
      }
      if (object instanceof AppPolicyController) {
        return;
      }
      logger.error("应用管理员,且为只读管理员无操作权限!");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    }

    /**
     * 部门管理员,且为应用管理员,且为只读管理员
     */
    if (PermissionsLabeled.dept_app_reader_Admin.equals(roleFlag)) {
      if (object instanceof DepartmentController) {
        return;
      }
      if (object instanceof UserController) {
        return;
      }
      if (object instanceof GroupController) {
        return;
      }
      if (object instanceof AppController) {
        return;
      }
      if (object instanceof AppPolicyController) {
        return;
      }
      logger.error("部门管理员,且为应用管理员,且为只读管理员无操作权限");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    }
  }

具有专门功能的管理员权限控制的切点选择

因为具有专门的管理员权限比较特殊,楼主采用的方式除了通用访问权限之外的controller全切,特殊情况在代码逻辑里面做实现即可。配置文件代码如下:

<aop:config>
    <!--定义切面 -->
    <aop:aspect id="authAspect" ref="usersPermissionsAdvice">
      <!-- 定义切入点 (配置在com.thundersoft.metadata.web.controller下所有的类在调用之前都会被拦截) -->
      <aop:pointcut
          expression="(execution(* com.thundersoft.metadata.web.controller.*.*(..)) and (
          !execution(* com.thundersoft.metadata.web.controller.FindPasswordController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.SelfServiceController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.HomeController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.UserStatusController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.DashboardController.*(..)) and
          !execution(* com.thundersoft.metadata.web.controller.MainController.*(..))))"
          id="appAuthPointCut"/>
      <!--方法被调用之前执行的 -->
      <aop:before method="appDeptAuth"
            pointcut-ref="appAuthPointCut"/>
    </aop:aspect>
  </aop:config>

##权限管理的切面代码实现

/**
   * 对应用管理员以及部门管理员进行aop拦截判断.
   * @param joinPoint 切入点.
   * @throws IOException
   */
  public void appDeptAuth(JoinPoint joinPoint) throws IOException {
    /**
     * 获取被拦截的方法.
     */
    String methodName = joinPoint.getSignature().getName();

    /**
     * 获取被拦截的对象.
     */
    Object object = joinPoint.getTarget();
    logger.info("权限管理aop,方法名称",methodName);
    HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    String roleFlag = GetLoginUserInfor.getLoginUserRole(request);

    /**
     * 超级管理员
     */
    if (PermissionsLabeled.super_Admin.equals(roleFlag)) {
      return;
    }

    /**
     * 应用管理员做数据更改权限的判断
     */
    if (PermissionsLabeled.app_Admin.equals(roleFlag)) {
      if (object instanceof AppController) {
        return;
      }
      if (object instanceof AppPolicyController) {
        return;
      }
      logger.error("应用管理员无操作权限");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    } else if (PermissionsLabeled.dept_Admin.equals(roleFlag)) {
      if (object instanceof DepartmentController) {
        return;
      }
      if (object instanceof UserController) {
        return;
      }

      if (object instanceof GroupController) {
        return;
      }
      if ("getAllDepartments".equals(methodName)) {
        return;
      }
      logger.error("应用管理员无操作权限");
      response.sendRedirect(request.getContextPath() + "/auth/readOnly");
    } else {
      return;
    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringData JPA中@OneToMany和@ManyToOne的用法详解

    SpringData JPA中@OneToMany和@ManyToOne的用法详解

    这篇文章主要介绍了SpringData JPA中@OneToMany和@ManyToOne的用法详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 通过AOP环绕通知如何实现事务控制

    通过AOP环绕通知如何实现事务控制

    这篇文章主要介绍了通过AOP环绕通知如何实现事务控制的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java 实现Comparable接口排序,升序、降序、倒叙

    java 实现Comparable接口排序,升序、降序、倒叙

    这篇文章主要介绍了java 实现Comparable接口排序,升序、降序、倒叙,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • 解析Java并发Exchanger的使用

    解析Java并发Exchanger的使用

    Exchanger是java 5引入的并发类,Exchanger顾名思义就是用来做交换的。这里主要是两个线程之间交换持有的对象。当Exchanger在一个线程中调用exchange方法之后,会等待另外的线程调用同样的exchange方法。两个线程都调用exchange方法之后,传入的参数就会交换。
    2021-06-06
  • Java8中Stream流求最大值最小值的实现示例

    Java8中Stream流求最大值最小值的实现示例

    本文主要介绍了Java8中Stream流求最大值最小值的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • mybatis中数据加密与解密的实现

    mybatis中数据加密与解密的实现

    数据加解密的实现方式多种多样,在mybatis环境中数据加解密变得非常简单易用,本文主要介绍了mybatis中数据加密与解密的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 详解JVM系列之对象的锁状态和同步

    详解JVM系列之对象的锁状态和同步

    锁和同步是java多线程编程中非常常见的使用场景。为了锁定多线程共享的对象,Java需要提供一定的机制来实现共享对象的锁定。当第二个线程进入同一个区域的时候,必须等待第一个线程解锁该对象。JVM是怎么做到的呢?快来一起看看吧。
    2021-06-06
  • 教你怎么使用hadoop来提取文件中的指定内容

    教你怎么使用hadoop来提取文件中的指定内容

    发现有很多小伙伴不会使用hadoop来提取文件中的指定内容,今天特地整理了这篇文章,文中有非常详细的代码示例,对不会这个方法的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • 2020JDK1.8安装教程详解(一次就可安装成功)

    2020JDK1.8安装教程详解(一次就可安装成功)

    这篇文章主要介绍了2020JDK1.8安装教程详解(一次就可安装成功),本文通过图文并茂的形式分步骤给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-08-08
  • 浅谈Java消息队列总结篇(ActiveMQ、RabbitMQ、ZeroMQ、Kafka)

    浅谈Java消息队列总结篇(ActiveMQ、RabbitMQ、ZeroMQ、Kafka)

    这篇文章主要介绍了浅谈Java消息队列总结篇(ActiveMQ、RabbitMQ、ZeroMQ、Kafka),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05

最新评论