云自無心水自閑

          天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
          posts - 288, comments - 524, trackbacks - 0, articles - 6
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          在上一篇中我們研究了如何實現SpringSecurity中Jsp Tag的<security:authorize ifAllGranted="ROLE_SUPERVISOR">的功能。這一次我們一起研究一下如何實現在Tapestry5.1中添加一個Filter來對所有的操作進行權限的過濾控制。
          在SpringSecurity中,我們一般是在application-context.xml中,添加一個SpringSecurity的Filter,然后在另外一個xml中詳細配置如何根據Url的規則進行權限的控制。而Tapestry的哲學是盡量減少Xml中的配置(其IOC容器也基本上是借鑒Guice而不Spring的),所以我們也是在代碼中實現權限規則的控制。
          總體上來看,可以用兩種方式來實現url規則,一種是Request級別的Filter,一種是頁面組件級別的Filter,如果是Request級別的話,可以從Request對象中獲取Url路徑,這樣就與SpringSecurity基本一樣了。本文主要介紹頁面組件級別的Filter,從中我們也可以體會到Tapestry5.1中的IOC容器的強大和便利。

          這就是Filter的代碼,這個Filter必須實現ComponentRequestFilter接口。值得注意的是其構造函數所需要用到的4個參數,這4個參數都是Tapestry5本身自有的服務,所以我們什么也不用做,Tapestry5自動會將服務的實例注入進來,這就是Tapestry-IOC的威力。
          ComponentRequestFilter接口一共有4個方法需要實現,具體代碼如下:

           1 public class RequiresLoginFilter implements ComponentRequestFilter {
           2 
           3     private final PageRenderLinkSource renderLinkSource;
           4 
           5     private final ComponentSource componentSource;
           6 
           7     private final Response response;
           8    
           9     private final ApplicationStateManager appStateManager;
          10    
          11     public RequiresLoginFilter(PageRenderLinkSource renderLinkSource,
          12             ComponentSource componentSource, Response response,
          13             ApplicationStateManager appStateManager
          14             ) {
          15         this.renderLinkSource = renderLinkSource;
          16         this.componentSource = componentSource;
          17         this.response = response;
          18         this.appStateManager = appStateManager;
          19     }
          20 
          21     public void handleComponentEvent(
          22             ComponentEventRequestParameters parameters,
          23             ComponentRequestHandler handler) throws IOException {
          24 
          25         if (dispatchedToLoginPage(parameters.getActivePageName())) {
          26             return;
          27         }
          28 
          29         handler.handleComponentEvent(parameters);
          30 
          31     }
          32 
          33     public void handlePageRender(PageRenderRequestParameters parameters,
          34             ComponentRequestHandler handler) throws IOException {
          35         if (dispatchedToLoginPage(parameters.getLogicalPageName())) {
          36             return;
          37         }
          38         handler.handlePageRender(parameters);
          39 
          40     }
          41 
          42     private boolean dispatchedToLoginPage(String pageName) {
          43         Component page = componentSource.getPage(pageName);
          44        
          45         if (page.getClass().isAnnotationPresent(RequiresLogin.class)) {
          46             if ( ! appStateManager.exists(Authentication.class)) {
          47                 redirect();
          48                 return true;
          49             }
          50             Authentication auth = appStateManager.get(Authentication.class);
          51             if ( auth == null ) {
          52                 redirect();
          53                 return true;
          54             }
          55            
          56              if ( ! auth.isLoggedIn()) {
          57                  redirect();
          58                  return true;
          59              }
          60 
          61             RequiresLogin requireLogin = page.getClass().getAnnotation(
          62                     RequiresLogin.class);
          63             String ifNotGranted = requireLogin.ifNotGranted();
          64             String ifAllGranted = requireLogin.ifAllGranted();
          65             String ifAnyGranted = requireLogin.ifAnyGranted();
          66             boolean permitted = auth.checkPermission(ifNotGranted, ifAllGranted, ifAnyGranted);
          67             if ( ! permitted ) {
          68                 return true;
          69             }
          70         }
          71 
          72         return false;
          73     }
          74    
          75     private void redirect() {
          76          Link link = renderLinkSource.createPageRenderLink("Logout");
          77        
          78          try {
          79              response.sendRedirect(link);
          80          } catch (Exception e) {
          81          }
          82     }
          83 
          84 }

          在ComponentRequestFilter中,我們無法使用@SessionState注解來直接注入Session中的變量,但是我們可以通過ApplicationStateManager來取得。

          現在我們需要把剛定義的Filter注冊到系統中,很簡單,只要在AppModule中添加以下函數就行了:

          1 public static void contributeComponentRequestHandler(
          2                 OrderedConfiguration<ComponentRequestFilter> configuration) {
          3         configuration.addInstance("RequiresLogin", RequiresLoginFilter.class);
          4 }
          5 
          從本例子中我們可以看到Tapesty Ioc容器使用的便利性,也認識到了Ioc容器在Tapestry體系中的重要性


          評論

          # re: Tapestry最新版5.1.0.5教程(九):權限控制框架的實現-進階篇  回復  更多評論   

          2010-12-25 23:22 by linuxboy
          這個方法我正在使用,但是有一個不是很完美的地方:用戶登錄后不能返回上一個頁面,尤其是包含context參數的頁面或者是request parameters的頁面。
          比如:http://none.com/edituser/12
          http://none.com/edituser?userId=12
          主站蜘蛛池模板: 城市| 河曲县| 辽中县| 名山县| 乡城县| 潼关县| 涡阳县| 陕西省| 克什克腾旗| 新竹市| 藁城市| 永登县| 沽源县| 襄樊市| 光山县| 米林县| 麦盖提县| 敦化市| 洛阳市| 津市市| 柘荣县| 太仆寺旗| 晋州市| 清水县| 上饶县| 襄垣县| 兴义市| 霍山县| 若羌县| 汝阳县| 额济纳旗| 蕲春县| 疏附县| 乐至县| 武邑县| 广东省| 罗甸县| 静海县| 苍山县| 盐亭县| 都安|