spring aop implements permission management

Problem stems from project development

Recently, a permission management module needs to be built in the project. According to the previous practice of my colleagues, it is necessary to make logical judgments before each interface call of the controller layer. There is nothing wrong with this, but the code repetition rate is too high, and it is manual labor, so , there is the use of spring aop as a point-cut to realize the permission management of general functions as mentioned in the title, which also reduces the scalability of the later development of the project.

Code implementation and configuration file for permission management

With minimal code modification, aop is undoubtedly the most ideal choice. There are various combinations of permissions in the project, and the logic complexity is relatively high, so step by step. Because the permissions involve the invocation of the back-end interface, the landlord chooses to use the controller layer code as the aspect, and the point of entry is each method block in the controller. For general access permissions, we use the execution expression to exclude.

Implementation of read-only administrator privileges and point-cut selection

For the realization of the exclusion of the general controller, the landlord uses the logic operation of the execution expression. Because the read-only administrator has the global read permission, and for the addition, deletion and modification permissions, the landlord adopts the method of adding, deleting and modifying using the pointcut, so, the standardized method naming is very important at this time. For various administrators that are compounded with read-only administrators, we can make special judgments in the code. The following is the configuration file configuration method of spring aop.


<!--非法权限抛出异常的spring mvc的处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="com.thundersoft.metadata.exception.AccessDeniedException">forward:/auth/readOnly</prop>
        </props>
    </property>
</bean>

 <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>

Read-only administrator rights management code implementation

So much has been said above, no more nonsense, the following is the aspect code implementation of the control of read-only permissions and various composite permissions.

 /**
     * 对只读管理员以及其复合管理员进行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)) {
            if (methodName.contains("redirectToLogout")) {
                return;
            }
            logger.error("只读管理员无操作权限!");
            throw new AccessDeniedException("您无权操作!");
        }

        /**
         * 部门管理员,且为只读管理员,
         */
        if (PermissionsLabeled.dept_reader_Admin.equals(roleFlag)) {
            if (object instanceof DepartmentController) {
                return;
            }

            if (object instanceof UserController) {
                if (methodName.contains("addAdmin")) {
                    throw new AccessDeniedException("您无权操作!");
                }

                if (methodName.contains("deleteAdmin")) {
                    throw new AccessDeniedException("您无权操作!");
                }

                if (methodName.contains("updateAdmin")) {
                    throw new AccessDeniedException("您无权操作!");
                }
                return;
            }

            if (object instanceof GroupController) {
                return;
            }
            logger.error("部门管理员,且为只读管理员无操作权限!");
            throw new AccessDeniedException("您无权操作!");
        }

        /**
         * 应用管理员,且为只读管理员
         */
        if (PermissionsLabeled.app_reader_Admin.equals(roleFlag)) {
            if (object instanceof AppController) {
                return;
            }

            if (object instanceof AppPolicyController) {
                return;
            }
            logger.error("应用管理员,且为只读管理员无操作权限!");
            throw new AccessDeniedException("您无权操作!");
        }

        /**
         * 部门管理员,且为应用管理员,且为只读管理员
         */
        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("部门管理员,且为应用管理员,且为只读管理员无操作权限");
            throw new AccessDeniedException("您无权操作!");
        }
    }

Admin rights-controlled pointcut selection with specialized features

Because it is special to have special administrator rights, the landlord uses all controllers except for general access rights, and special cases can be implemented in the code logic. The configuration file code is as follows:

 <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>

Aspect code implementation of permission management

 /**
     * 对应用管理员以及部门管理员进行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("应用管理员无操作权限");
            throw new AccessDeniedException("您无权操作!");
        } 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("应用管理员无操作权限");
            throw new AccessDeniedException("您无权操作!");
        } else {
            return;
        }
    }

Custom permission illegal exception code


/**
 * @author [email protected]
 * @date 2017/12/12
 */
public class AccessDeniedException extends RuntimeException {

    /**
     * Constructs a <code>AccessDeniedException</code> with the specified message.
     *
     * @param msg the detail message.
     */
    public AccessDeniedException(String msg) {
        super(msg);
    }

    /**
     * Constructs a {@code AccessDeniedException} with the specified message and root cause.
     *
     * @param msg the detail message.
     * @param t root cause
     */
    public AccessDeniedException(String msg, Throwable t) {
        super(msg, t);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325949704&siteId=291194637