使用Struts2的攔截器和自定義注解方式實現權限控制

lyc1976 8年前發布 | 15K 次閱讀 Struts Struts2 Web框架

1. 自定義注解的編寫:@interface

說明:使用Spring的AOP也可以實現權限的控制,但是經過Spring的AOP方法處理后再交給Struts2時,注意Struts2中上下文參數丟失問題。

Struts2的攔截器使用了動態代理,從動態代理類中獲取調用方法名并通過invocation.getAction().getClass().getMethod(methodName)獲取被調用的方法。然后根據session中保存的用戶權限和從方法注解中獲取的權限進行判斷,看用戶是否具有調用該方法的權限進行處理。

下面是使用Struts2的Interceptor攔截器實現權限控制的例子:

這里我們使用注解為每個Action的方法聲明權限。

首先創建自定義注解Permission,用于設置權限:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission {
    /** 權限名稱 */
    String privilege();
}

其中的Permission的module和privilege為模塊和模塊對應的權限,每個用戶登錄時都把權限信息保存到session中,方便在攔截器中對權限的判斷。

2. Struts2 Interceptor攔截器的編寫和配置

1、 編寫一個攔截器實現Interceptor接口或者繼承AbstractInterceptor

接下來最重要的就是編寫攔截器對權限進行判斷,并作出正確的處理:

public class PrivilegeInterceptor extends AbstractInterceptor {

private static final long serialVersionUID = 742285864455102141L;

/**
 * 1、通過動態代理類和反射機制獲取調用的方法
 * 2、獲取方法的Permission注解
 * 3、獲取Permission中包含的權限信息(構造SystemPrivilege權限類)
 * 4、和用戶的權限信息進行對比(PrivilegeGroup中的SystemPrivilege)判斷用戶的權限
 */
@Override
public String intercept(ActionInvocation invocation) throws Exception {

    HttpServletRequest request = ServletActionContext.getRequest();
    if(WebUtil.getRequestURI(request).startsWith("/cms/control/")){
        ActionProxy actionProxy = invocation.getProxy();
        String methodName = actionProxy.getMethod();
        if (StringUtils.isBlank(methodName)) {
            methodName = "execute";//默認方法
        }
        Class aClass = actionProxy.getAction().getClass();
        Method method = aClass.getMethod(methodName);   
        if(method != null && method.isAnnotationPresent(Permission.class)){
            System.out.println("Call the Action Method:" + method.toString());
            //獲取當期執行的Action上的注解
            Permission permission = method.getAnnotation(Permission.class);
            if (permission != null) {
                System.out.println("當前需要的權限為:" + permission.module());
                //獲取當期執行的Action方法需要的權限
                SystemPrivilege methodPrivilege = new SystemPrivilege(permission.privilege());
                //WebUtil.getEmployee(request) 方法是從session中獲取保存的employee信息,包括權限集合
                Employee employee = WebUtil.getEmployee(request);
                //循環判斷用戶是否具有該權限,如果有則繼續執行,否則返回提示視圖
                for(PrivilegeGroup group : employee.getGroups()){
                    if(group.getPrivileges().contains(methodPrivilege)){
                        return invocation.invoke();
                    }
                }
                System.out.println("權限不足");
                return "privilegemessage";
            }
        }
        System.out.println("未設置權限");
        return invocation.invoke();
    }
    System.out.println("所有權限");
    return invocation.invoke();
}

}</code></pre>

2、 在struts.xml文件中注冊自定義攔截器

3、 在需要使用的Action中引用自定義攔截器。

在想要設置權限的方法加入自定義的Permission注解用于標識該方法的權限:

@Permission(privilege="confirmOrder")
public String confirmOrder(){
    …
}

3. Struts2攔截器原理

AOP面向切面編程和動態代理

下面開始講一下主菜ActionProxy了,在這之前最好先去了解一下動態Proxy的基本知識。

ActionProxy是Action的一個代理類,也就是說Action的調用是通過ActionProxy實現的,其實就是調用了ActionProxy.execute()方法,而該方法又調用了ActionInvocation.invoke()方法。歸根到底,最后調用的是DefaultActionInvocation.invokeAction()方法。

DefaultActionInvocation()->init()->createAction()。

最后通過調用

ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction() 這里的步驟是先由ActionProxyFactory創建ActionInvocation和ActionProxy。

一個請求在Struts2框架中的處理分為以下幾個步驟:

1.客戶端發出一個指向servlet容器的請求(tomcat);

2.這個請求會經過圖中的幾個過濾器,最后會到達FilterDispatcher過濾器。

3.過濾器FilterDispatcher是struts2框架的心臟,在處理用戶請求時,它和請求一起相互配合訪問struts2的底層框架結構。在web容器啟動時,struts2框架會自動加載配置文件里相關參數,并轉換成相應的類。

如:ConfigurationManager、ActionMapper和ObjectFactory。ConfigurationManager 存有配置文件的一些基本信息,ActionMapper存有action的配置信息。在請求過程中所有的對象(Action,Results,Interceptors,等)都是通過ObjectFactory來創建的。過濾器會通過詢問ActionMapper類來查找請求中需要用到的Action。

4.如果找到需要調用的Action,過濾器會把請求的處理交給ActionProxy。ActionProxy為Action的代理對象。ActionProxy通過ConfigurationManager詢問框架的配置文件,找到需要調用的Action類。

5.ActionProxy創建一個ActionInvocation的實例。ActionInvocation在ActionProxy層之下,它表示了Action的執行狀態,或者說它控制的Action的執行步驟。它持有Action實例和所有的Interceptor。

6.ActionInvocation實例使用命名模式來調用,1. ActionInvocation初始化時,根據配置,加載Action相關的所有Interceptor。2. 通過ActionInvocation.invoke方法調用Action實現時,執行Interceptor。在調用Action的過程前后,涉及到相關攔截器(intercepetor)的調用。

7. 一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。在表示的過程中可以使用Struts2 框架中繼承的標簽。

 

來自:http://www.linkedkeeper.com/detail/blog.action?bid=60

 

 本文由用戶 lyc1976 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!