Privilege Control Series 3 - Fine-grained control privileges using interceptors

Keywords: Database log4j Spring

Preface

  • The granularity of permissions can be fine-grained, and can even be partitioned to each method in the code. As long as the user does not have permission to access a CRUD method, we can intercept it.

General thinking

  • Add a global interceptor to intercept the user's request and determine whether the user has permission to request this method. If the user has permission, it will release it. If the user has no permission, it will intercept, prompting the user to have no permission to use this function.

Custom Annotation Code

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationLimit {
    String mid();
    String pid();
}

Interceptor code

public class ErrorAndLimitInterceptor extends MethodFilterInterceptor {

    /**Interceptor*/
    @Override
    protected String doIntercept(ActionInvocation actioninvocation) throws Exception {
        //Place custom error information in request
        HttpServletRequest request = (HttpServletRequest) actioninvocation
                        .getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
        try {
            //Get the action object of the request
            Object action = actioninvocation.getAction();
            //Get the name of the method requested
            String methodName = actioninvocation.getProxy().getMethod();
            //Get the encapsulated class of the method in action (the method in action has no parameters)
            Method method = action.getClass().getMethod(methodName, null);
            // Return value of Action   
            String result = null; 
            boolean flag=isCheckLimit(request,method);
            if (flag) {
                //Run the intercepted Action and catch if an exception occurs during the interval
                result=actioninvocation.invoke();
            }else{
                request.setAttribute("errorMsg", "Sorry, you do not have permission to operate this function.");
                return "errorMsg";
            }
            return result;
        } catch (Exception e) {
            /**  
             * Handling exceptions  
             */
            String errorMsg = "Error message appears, please check the log!";
            //Determine exactly what type of exception is by instanceof   
            if (e instanceof RuntimeException) {
                //Unknown runtime exception   
                RuntimeException re = (RuntimeException) e;
                //re.printStackTrace();
                errorMsg = re.getMessage().trim();
            }
            /**  
             * Send an error message to the page  
             */
            request.setAttribute("errorMsg", errorMsg);

            /**  
             * log4j Log  
             */
            Log log = LogFactory
                    .getLog(actioninvocation.getAction().getClass());
            log.error(errorMsg, e);
            return "errorMsg";
        }  
    }


    private boolean isCheckLimit(HttpServletRequest request, Method method) {
        if (method==null) {
            return false;
        }
        //Get the current logged-in user
        ElecUser elecUser=(ElecUser)request.getSession().getAttribute("globle_user");
        if (elecUser==null) {
            return false;
        }

        //Get the role of the current logged-in user
        Hashtable<String,String> ht =(Hashtable<String, String>) request.getSession().getAttribute("globle_role");
        if (ht==null) {
            return false;
        }

        //Processing annotations and judging whether there are annotations in the method
        boolean isAnnotationPresent=method.isAnnotationPresent(AnnotationLimit.class);
        //There is no comment
        if (!isAnnotationPresent) {
            return false;
        }

        //Existence annotations (call annotations)
        AnnotationLimit limit=method.getAnnotation(AnnotationLimit.class);
        //Get the value on the annotation
        String mid=limit.mid();
        String pid=limit.pid();

        //Use mid pid on the role ID annotation to query whether the role is used for permissions of this method in the database

        boolean flag=false;
        //The interceptor loads the spring container to obtain the Service class and queries the corresponding user information using the Service class.
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
        IElecRoleService elecRoleService = (IElecRoleService)wac.getBean(IElecRoleService.SERVICE_NAME);
        if (ht!=null && ht.size()>0) {
            for (Iterator<Entry<String, String>> ite = ht.entrySet().iterator();ite.hasNext();) {
                Entry<String,String> entry=ite.next();
                //Get the role id
                String roleId =entry.getKey();
                flag=elecRoleService.findRolePopedomByID(roleId,mid,pid);
                if (flag) {
                    break;
                }
            }
        }
        return flag;
    }

}

Interceptor configuration

<interceptors>
   <! - Declare the interceptor - >
   <interceptor name="errorAndLimitInterceptor" class="com.itheima.elec.utils.ErrorAndLimitInterceptor" />
   <! - Configure the interceptor stack - >
   <interceptor-stack name="myErrorAndLimitInterceptor">
    <interceptor-ref name="defaultStack" />
      <interceptor-ref name="errorAndLimitInterceptor" >
      <param name="excludeMethods">menuHome,title,left,change,loading,logout,alermStation,alermDevice,showMenu
      </param>
      </interceptor-ref>
   </interceptor-stack>
</interceptors>
<! - The interceptor stack that covers the underlying layer is valid for all action s in the package - >
<default-interceptor-ref name="myErrorAndLimitInterceptor"/>

Annotations to add permissions to methods

@AnnotationLimit(mid="an",pid="am")
    public String home() {
        //Method body
        .......
        .......
        return "home";
    }

Summary

  • The function of the code in the interceptor is to read the annotation code on the body of the method. The annotation code stores the access information of the method. After the user gets the privilege information, he adds his role id. Then he uses the information to check whether the user has the privilege in the database. If he has the privilege, he releases it, otherwise he intercepts it. To do this, we control the granularity of permissions on each method, and we can enter the Url address in the browser's address bar without accessing illegal pages.

Posted by imawake on Thu, 11 Apr 2019 09:18:31 -0700