The problem stems from project development

Recently, a permission management module needs to be made in the project. According to the practice of my former colleague, logical judgment should be made before each interface of the Controller layer is called, which is not improper, but the code repetition rate is too high, and physical labor is required. So, As mentioned above, spring AOP is used as a pointcut to implement permissions management for common functions, which reduces the extensibility of late project development.

Authority management code implementation and configuration files

With minimal code modification, AOP is definitely the best choice. There are a variety of permissions in the project compound, relatively high logical complexity, so step by step. Because permissions involve calls to back-end interfaces, the controller layer code is cut to the point where each method block in the Controller is cut to the point. For general access permissions, we use execution expressions to exclude them.

The realization of read-only administrator authority and the choice of the cut point

The execution expression logic is used to implement the generic controller. Because the read-only administrator has the global read permission, and for the increase, deletion and change permission, the landlord is using the cut point is the increase, deletion and change method, so, this time the standard method name is very important. For the various administrators that compound with read-only administrators, we can make a special judgment in the code. Here is the configuration file configuration method for Spring AOP.

<! Spring MVC handling of illegal permissions that throw exceptions --> <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"> <! - definition entry point (configuration in com. Thundersoft. Metadata. Web. All the classes under the controller will be intercepted before calling) - > < 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>
Copy the code

Read-only administrator authority management code

So much said above, without further ado, the following is the control of read-only permissions and various compound permissions of the faceted code implementation.

/** * Aop interception judgment for read-only administrators and their compound administrators * @param joinPoint pointcut * @throws IOException */ public voidreadOnly(JoinPoint JoinPoint) throws IOException {/** * Obtains the intercepted method. */ String methodName = joinPoint.getSignature().getName(); */ Object Object = joinPoint.gettarget (); logger.info("Permission management AOP, method name {}"+ methodName); HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); String roleFlag = GetLoginUserInfor.getLoginUserRole(request); /** * Super administrator */if (PermissionsLabeled.super_Admin.equals(roleFlag)) {
            return; } /** * The read-only administrator determines the permission to change data */if (PermissionsLabeled.reader_Admin.equals(roleFlag)) {
            if (methodName.contains("redirectToLogout")) {
                return;
            }
            logger.error("Read-only administrator has no operation rights!");
            throw new AccessDeniedException("You have no authority!"); } /** * Department administrator, and read-only administrator, */if (PermissionsLabeled.dept_reader_Admin.equals(roleFlag)) {
            if (object instanceof DepartmentController) {
                return;
            }

            if (object instanceof UserController) {
                if (methodName.contains("addAdmin")) {
                    throw new AccessDeniedException("You have no authority!");
                }

                if (methodName.contains("deleteAdmin")) {
                    throw new AccessDeniedException("You have no authority!");
                }

                if (methodName.contains("updateAdmin")) {
                    throw new AccessDeniedException("You have no authority!");
                }
                return;
            }

            if (object instanceof GroupController) {
                return;
            }
            logger.error("Department administrator and read-only administrator with no operation permission!");
            throw new AccessDeniedException("You have no authority!"); } /** * The application administrator and read-only administrator */if (PermissionsLabeled.app_reader_Admin.equals(roleFlag)) {
            if (object instanceof AppController) {
                return;
            }

            if (object instanceof AppPolicyController) {
                return;
            }
            logger.error("Application administrator, and the read-only administrator has no operation permission!");
            throw new AccessDeniedException("You have no authority!"); } /** * Department administrator, an application administrator, and a read-only administrator */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("Department administrator, application administrator, and read-only administrator with no operation permission.");
            throw new AccessDeniedException("You have no authority!"); }}Copy the code

Pointcut selection for administrator permission control with special features

Because it has special administrator permissions, the way adopted by the owner of the building is to cut all the controller in addition to the general access permissions. In special cases, it can be realized in the code logic. The configuration file code is as follows:

<aop:config> <! Aop :aspect id="authAspect" ref="usersPermissionsAdvice"> <! - definition entry point (configuration in com. Thundersoft. Metadata. Web. All the classes under the controller will be intercepted before calling) - > < 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>
Copy the code

Authority management section code implementation

* @param joinPoint pointcut * @throws IOException */ public void appDeptAuth(joinPoint JoinPoint) throws IOException {/** * Gets the intercepted method. */ String methodName = joinPoint.getSignature().getName(); */ Object Object = joinPoint.gettarget (); logger.info("Permission management AOP, method name {}",methodName); HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); String roleFlag = GetLoginUserInfor.getLoginUserRole(request); /** * Super administrator */if (PermissionsLabeled.super_Admin.equals(roleFlag)) {
            return; } /** * The application administrator determines the permission to change data */if (PermissionsLabeled.app_Admin.equals(roleFlag)) {
            if (object instanceof AppController) {
                return;
            }

            if (object instanceof AppPolicyController) {
                return;
            }

            logger.error("Application administrator has no operation permission");
            throw new AccessDeniedException("You have no authority!");
        } 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("Application administrator has no operation permission");
            throw new AccessDeniedException("You have no authority!");
        } else {
            return; }}Copy the code

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);
    }
}

Copy the code

Blog initial link