spring aop реализует управление разрешениями

задняя часть

Проблема связана с разработкой проекта

В последнее время в проект необходимо встроить модуль управления разрешениями.По предыдущей практике моих коллег необходимо делать логические суждения перед каждым вызовом интерфейса слоя контроллера.В этом нет ничего плохого,но повторение кода скорость слишком высока, и это ручной труд, поэтому используется spring aop в качестве точечного сокращения для реализации управления разрешениями общих функций, как указано в заголовке, что также снижает масштабируемость более поздней разработки проект.

Реализация кода и файл конфигурации для управления разрешениями

С минимальной модификацией кода, aop, несомненно, является самым идеальным выбором. В проекте есть разные комбинации разрешений, а сложность логики относительно высока, поэтому пошагово. Поскольку разрешения включают вызов внутреннего интерфейса, арендодатель решает использовать код уровня контроллера для создания поверхности разреза, а точкой отсечения является каждый блок метода в контроллере.Для общих прав доступа мы используем выражение выполнения исключить.

Внедрение привилегий администратора только для чтения и выбора точечного разреза

Для реализации исключения генерального контроллера арендодатель использует логическую операцию исполнительного выражения. Поскольку администратор только для чтения имеет глобальное разрешение на чтение, а для разрешений на добавление, удаление и изменение арендодатель использует метод добавления, удаления и изменения с использованием pointcut, поэтому стандартизированное именование методов очень важно в настоящее время. Для различных администраторов, которые объединены с администраторами только для чтения, мы можем сделать специальные суждения в коде. Ниже приведен метод настройки файла конфигурации 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>

Реализация кода управления правами администратора только для чтения

Столько всего было сказано выше, больше никакой чепухи, далее следует аспект кода реализации управления разрешениями только для чтения и различными составными разрешениями.

 /**
     * 对只读管理员以及其复合管理员进行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("您无权操作!");
        }
    }

Выбор pointcut, контролируемый правами администратора, со специальными функциями

Поскольку специальные права администратора являются особыми, арендодатель использует все контроллеры, кроме прав общего доступа, и в логике кода могут быть реализованы особые случаи. Код конфигурационного файла выглядит следующим образом:

 <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("应用管理员无操作权限");
            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;
        }
    }

Недопустимый код исключения пользовательского разрешения


/**
 * @author wuhf0703@thundersoft.com
 * @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);
    }
}

первая ссылка в блоге