熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

動態Proxy與Java ACL用戶訪問控制機制實現

2013-11-15 11:39:54  來源: JSP教程 

  用戶訪問控制(Access control )機制總是圍繞粗粒度和細粒度兩個方面來討論
  粗粒度控制可以規定訪問整個對象或對象群的某個層而細粒度控制則總是在方法或屬性層進行控制比如
  允許一個文件為只讀是屬於粗粒度控制而允許對這個文件某行有寫操作則屬於細粒度控制
  一個好的用戶控制機制當然既允許粗粒度也允許細粒度控制在Jive中我們看到是使用Proxy來達到這個目的但是我們也發現由於需要對每個類都要進行細粒度控制所以必然對每個類都要做一個Proxy類這樣帶來了很多Proxy類如ForumProxy ForumThreadProxy ForumFactoryProxy等無形增加了系統復雜性
  
    使用動態Proxy可以很好的解決這個問題再結合javasecurityacl的ACL機制我們就可以靈活地實現粗粒度和細粒度的雙重控制
  
    當一個用戶login後我們就要在內存中為其建立相應的授權訪問機制使用javasecurityacl可以很方便的建立這樣一個安全系統
  
    首先任何一個對象都應該有個基本屬性擁有者 或擁有者所屬組(Windows中每個目錄安全描述符都由部分構成對象的創建者對象所屬的組自由存取控制和系統存取控制)
   Java acl開始第一步是建立一個主體 Principal其中SecurityOwner是主體的擁有者 private static final Principal _securityOwner = new PrincipalImpl(SecurityOwner);
   當用戶login進來時他帶有兩個基本數據訪問密碼和他要訪問的對象ApplicationName首先驗證用戶名和密碼然後從數據庫中取出其權限數據建立Permission這裡使用Feature繼承了Permission在Feature中定義了有關權限的細節數據(如讀 寫 刪)
  // 取出用戶和被訪問對象之間的權限關系這種權限關系可能不只一個也就是說用戶
  //可能對被訪問對象擁有讀 寫 刪等多個權限將其打包在Hasbtable中
  Hashtable features = loadFeaturesForUser(sApplicationName sUserID);
   創建一個用戶對象
  User user = new UserImpl(sUserID new Hashtable() );
   為這個用戶創建一個活動的acl entry
  addAclEntry( user features);
  其中最關鍵的是第四步addAclEntry我們看看其如何實現的
  // 為這個用戶創建一個新的Acl entry
  AclEntry newAclEntry = new AclEntryImpl( user);
  
  //遍歷Hashtable features將其中多種權限加入:
  
  feature = (Feature) hFeaturesget(keyName);
  newAclEntryaddPermission( feature );
  
  最後也要加入主體擁有者SecurityOwner
  這樣一個安全體系就已經建立完成
  當你在系統中要檢驗某個用戶使用擁有某個權限如讀的權利時只要
  aclcheckPermission(user feature )就可以acl是ACL的一個實例這樣權限檢查就交給
  javasecurityaclACL 去處理了
  有了ACL機制後我們就可以在我們系統中使用動態Proxy模式來對具體對象或方法進行控制比如我們有一個Report類有些用戶可以讀有些用戶可以寫(哪些用戶可以讀 哪些用戶可以寫已經在上面ACL裡部署完成)
  從Java 開始 Sun提供了Dynamic Proxy API為了使動態Proxy能夠工作第一你必須有一個Proxy接口還要有一個繼承InvocationHandler的Proxy類
  在下面的例子中我們設定有三種用戶普通人雇員經理權限是這樣普通人可以讀報告雇員和經理可以修改報告
  按通常思維我們對於讀權限我們設計一個具備讀的角色類
  public interface IpersonRO {
  public String getName();
  public String getAddress();
  public String getPhoneNumber();
  }
  類裡面都是讀的方法這是一種粗粒度訪問控制也就是說把讀寫權限只落實到類(對象)上這樣的話我們還要為寫的角色再建一個類很顯然這不是一個很好的方法使用動態proxy+acl就可以實現很好的細粒度控制
  public class ReportProxy implements InvocationHandler
  {
  
  private Map map;
  public static Object newInstance(Map mapClass[] interfaces)
  {
  return ProxynewProxyInstance(mapgetClass()getClassLoader() interfacesnew ReportProxy(map));
  }
  
  public ReportProxy(Map map)
  {
  thismap = map;
  }
  
  public Object invoke(Object proxy Method m Object[] args) throws Throwable
  {
  Object result;
  String methodName = mgetName();
  if (methodNamestartsWith(get))
  {
  if (!aclcheckPermission(user read)) return null;
  String name = methodNamesubstring(
  methodNameindexOf(get)+);
  return mapget(name);
  }
  else if (methodNamestartsWith(set))
  {
  if (!aclcheckPermission(user write)) return null;
  String name = methodNamesubstring(
  methodNameindexOf(set)+);
  mapput(name args[]);
  return null;
  }
  else if (methodNamestartsWith(is))
  {
  if (!aclcheckPermission(user read)) return null;
  String name = methodNamesubstring(
  methodNameindexOf(is)+);
  return(mapget(name));
  }
  return null;
  }
  }
  

From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19404.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.