差沙的密碼 -- SSHWSFC's code
          閱讀本Blog請自備塑料袋一只
          posts - 14,  comments - 59,  trackbacks - 0
          Acegi好早就實現了ACL(好像是0.5),但是使用起來確實有點麻煩,所以用的不是太廣泛。這里簡單的說明一下使用方法,希望有更多的朋友來試試。

          首先要理解Acegi里面Voter的概念,ACL正是在一個Voter上擴展起來的。現來看一下AclVoter的配置。

          ????<bean?id="aclBeanReadVoter"?class="org.acegisecurity.vote.BasicAclEntryVoter">
          ????????
          <property?name="processConfigAttribute">
          ????????????
          <value>ACL_READ</value>
          ????????
          </property>
          ????????
          <property?name="processDomainObjectClass">
          ????????????
          <value>org.springside.modules.security.acl.domain.AclDomainAware</value>
          ????????
          </property>
          ????????
          <property?name="aclManager">
          ????????????
          <ref?local="aclManager"/>
          ????????
          </property>
          ????????
          <property?name="requirePermission">
          ????????????
          <list>
          ????????????????
          <ref?local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/>
          ????????????????
          <ref?local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/>
          ????????????
          </list>
          ????????
          </property>
          ????
          </bean>
          1. ACL_READ指的是這個Voter對哪些SecurityConfig起作用,我們可以把ACL_READ配置在想要攔截的Method上。比方說我們要攔截readOrder這個方法,以實現ACL控制,可以這樣配置。
            orderManager.readOrder=ACL_READ
          2. processDomainObjectClass指出哪些DomainObject是要進行ACL校驗的。
          3. aclManager是一個比較重要的概念,主要負責在權限列表中根據用戶和DomainObject取得acl列表。
          4. requirePermission指出要進行這個操作必須具備的acl權限,比方說read操作就必須有ADMINISTRATION或READ兩個權限。

          其實整個過程看下來比較清晰,下面來看一下AclManager如何配置。

          ????<!--?=========?ACCESS?CONTROL?LIST?LOOKUP?MANAGER?DEFINITIONS?=========?-->

          ????
          <bean?id="aclManager"?class="org.acegisecurity.acl.AclProviderManager">
          ????????
          <property?name="providers">
          ????????????
          <list>
          ????????????????
          <ref?local="basicAclProvider"/>
          ????????????
          </list>
          ????????
          </property>
          ????
          </bean>

          ????
          <bean?id="basicAclProvider"?class="org.acegisecurity.acl.basic.BasicAclProvider">
          ????????
          <property?name="basicAclDao">
          ????????????
          <ref?local="basicAclExtendedDao"/>
          ????????
          </property>
          ????
          </bean>

          ????
          <bean?id="basicAclExtendedDao"?class="org.acegisecurity.acl.basic.jdbc.JdbcExtendedDaoImpl">
          ????????
          <property?name="dataSource">
          ????????????
          <ref?bean="dataSource"/>
          ????????
          </property>
          ????
          </bean>

          很明顯ACLManager繼承了Acegi的一貫風格,Provider可以提供多種取得ACL訪問列表的途徑,默認的是用basicAclProvider在數據庫中取得。既然提到了數據庫,那我們就來看一下Acegi默認提供的ACL在數據庫里的保存表結構:

          CREATE?TABLE?acl_object_identity?(
          id?
          IDENTITY?NOT?NULL,
          object_identity?VARCHAR_IGNORECASE(
          250)?NOT?NULL,
          parent_object?
          INTEGER,
          acl_class?VARCHAR_IGNORECASE(
          250)?NOT?NULL,
          CONSTRAINT?unique_object_identity?UNIQUE(object_identity),
          FOREIGN?KEY?(parent_object)?REFERENCES?acl_object_identity(id)
          );
          CREATE?TABLE?acl_permission?(
          id?
          IDENTITY?NOT?NULL,
          acl_object_identity?
          INTEGER?NOT?NULL,
          recipient?VARCHAR_IGNORECASE(
          100)?NOT?NULL,
          mask?
          INTEGER?NOT?NULL,
          CONSTRAINT?unique_recipient?UNIQUE(acl_object_identity,?recipient),
          FOREIGN?KEY?(acl_object_identity)?REFERENCES?acl_object_identity(id)
          );
          1. acl_object_identity表存放了所有受保護的domainObject的信息。其中object_identity字段保存了domainObject的class和id,默認的保存格式是:domainClass:domainObjectId。
          2. acl_permission?就是ACL權限列表了,recipient?是用戶或角色信息,mask表示了這個用戶或角色對這個domainObject的訪問權限。注意這些信息的保存格式都是可以根據自己的需要改變的。

          這樣讀取和刪除的時候Acegi就能很好的完成攔截工作,但是讀取一個List的時候,如何才能把該用戶不能操作的domainObject剔除掉呢?這就需要afterInvocationManager來完成這個工作。下面來看下配置:

          ????<!--?==============?"AFTER?INTERCEPTION"?AUTHORIZATION?DEFINITIONS?===========?-->

          ????
          <bean?id="afterInvocationManager"?class="org.acegisecurity.afterinvocation.AfterInvocationProviderManager">
          ????????
          <property?name="providers">
          ????????????
          <list>
          ????????????????
          <ref?local="afterAclCollectionRead"/>
          ????????????
          </list>
          ????????
          </property>
          ????
          </bean>
          ????
          <!--?Processes?AFTER_ACL_COLLECTION_READ?configuration?settings?-->
          ????
          <bean?id="afterAclCollectionRead"?class="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider">
          ????????
          <property?name="aclManager">
          ????????????
          <ref?local="aclManager"/>
          ????????
          </property>
          ????????
          <property?name="requirePermission">
          ????????????
          <list>
          ????????????????
          <ref?local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/>
          ????????????????
          <ref?local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/>
          ????????????
          </list>
          ????????
          </property>
          ????
          </bean>

          afterAclCollectionRead會在攔截的方法執行結束的時候執行。主要的作用就是在返回的List中挨個檢查domainObject的操作權限,然后根據requirePermission來剔除不符合的domainObject。
          posted @ 2006-06-17 00:20 差沙 閱讀(2275) | 評論 (4)編輯 收藏
          acegi1.0發布,其實有點出乎意料,因為我一向認為acegi的代碼已經相當穩定了,但是acegi力求精益求精,從新版還是能看到不少實用的改動和升級。這里簡單分析一下。

          [SEC-183] - Avoid unnecessary HttpSession creation when using Anonymous and Remember-Me authentication

          以前如果使用HttpSessionContextIntegrationFilter的話,不管你是否需要創建session,他都會給你創建。這在一些Base驗證的時候是多余的。現在加上了forceEagerSessionCreation,在創建session的時候做了控制。

          [SEC-29] - Save POST request parameters before redirect

          在前幾個版本出現這個問題,如果實現了登陸自動跳轉,acegi僅僅是簡單記錄了URL,沒有深入的紀錄信息。新版本中acegi不僅僅是保持POST中的數據不會丟失,request里面的東西幾乎全都序列化保存下來了,實現可以看看SavedRequest。

          [SEC-40] - HibernateDao.scroll() performance

          [SEC-92] - Hibernate ACL implementation

          這個比較激動的改進在1.0的源碼中沒有找到,看alex的意思好像是僅僅提供各演示,目的是為了生成數據腳本方便點。(其實這個還真的沒法做成特別通用的,畢竟每個人的ACL實現都有可能不同)

          [SEC-147] - BasicAclEntryAfterInvocationProvider should support processDomainObjectClass

          對List進行ACL交驗的時候,會把第一個元素取出,看看是否AssignableFrom這個processDomainObjectClass ,算是做一下安全檢查吧。

          [SEC-172] - Allow SimpleAclEntry to take 'null' as recipient constructor argument

          其實應該是不允許recipient 為空。

          [SEC-187] - inHttp & inHttps not fully utilized in AuthenticationProcessingFilterEntryPoint

          [SEC-191] - AclTag class should use the BeanFactoryUtils.beanNamesForTypeIncludingAncestors method to search for the AclManager

          AclTag在尋找AclManager 時候會更加靈活了,得益于spring的強大。

          <明天繼續吧。。。。>

          [SEC-194] - RememberMeServices should be available when using BasicAuth logins

          [SEC-195] - Create Acegi-backed CAS3 AuthenticationHandler

          [SEC-196] - Update web site and documentation to reference JA-SIG CAS

          [SEC-203] - Allow setting the AuthenticationManager onto the ConcurrentSessionController for inverted dependency

          [SEC-204] - Better detection of malformed text in FilterInvocationDefinitionSourceEditor

          [SEC-205] - Allow multiple URLs in DefaultInitialDirContextFactory

          [SEC-206] - TokenBasedRememberMeServices using context root when setting cookie paths (inc code)

          [SEC-207] - Implement countermeasures against session attacks

          [SEC-209] - Make AbstractProcessingFilter.eventPublisher field protected

          [SEC-217] - Improve Siteminder Filter

          [SEC-220] - Allow ExceptionTranslationFilter to not catch exceptions

          [SEC-221] - AbstractProcessingFilter.onPreAuthentication exceptions should be caught

          [SEC-224] - Make Authentication.getPrincipal() for CAS return the UserDetails

          [SEC-229] - Allow redirects to external URLs in AbstractProcessingFilter

          [SEC-231] - Add another DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles

          [SEC-234] - Allow WebAuthenticationDetails pluggable implementations

          [SEC-236] - JbossAcegiLoginModule to use ApplicationContext interface

          [SEC-238] - Add AuthenticationException to AbstractProcessingFilter.onUnsuccessfulAuthentication method signature

          [SEC-242] - Logger in AbstractProcessingFilter

          [SEC-244] - Column names instead of indexes for org.acegisecurity.userdetails.jdbc.JdbcDaoImpl

          [SEC-246] - Enable late-binding of UserDetailsService on DaoAuthenticationProvider

          [SEC-247] - Allow to specify resources that shouldn't be filtered in FilterChainProxy

          [SEC-251] - DefaultLdapAuthoritiesPopulator: Add filter argument {1} for username as in Tomcat JNDIRealm

          [SEC-255] - Reorder AuthenticationProcessingFilter to create HttpSession before delegating to AuthenticationDetailsSource

          [SEC-257] - ExceptionTranslationFilter to use strategy interface for AccessDeniedException handling

          [SEC-259] - AccessDecisionVoter: typo in JavaDoc

          [SEC-260] - AbstractAccessDecisionManager and loggers

          [SEC-262] - AbstractAccessDecisionManager needs standard handling ifAllAbstainDecisions

          [SEC-264] - Introduction of LdapUserDetails and changes to LdapAuthenticator and LdapAuthoritiesPopulator interfaces

          [SEC-276] - Restructure reference guide

          posted @ 2006-06-01 23:05 差沙 閱讀(558) | 評論 (0)編輯 收藏
          這兩天在springside受白衣的影響開始關注drools。說他是平民的腳本引擎一點都不假,使用起來極為方便,本來以為網上應該有不少的講解了,但是發現幾乎全是針對2.0版本講解的。而drools加入jboss后有了質的變化,下面來看一下最新的3.0使用起來有什么不同:

          首先我們要取得rule,規則引擎、規則引擎,取得規則是必要的。
          private?static?RuleBase?readRule()?throws?Exception?{
          ????????
          //read?in?the?source
          ????????Reader?source?=?new?InputStreamReader(?DroolsTest.class.getResourceAsStream(?"/aclcreat.drl"?)?);
          ????????
          ????????
          //optionally?read?in?the?DSL?(if?you?are?using?it).
          ????????Reader?dsl?=?new?InputStreamReader(?DroolsTest.class.getResourceAsStream(?"/mylang.dsl"?)?);

          ????????
          //Use?package?builder?to?build?up?a?rule?package.
          ????????
          //An?alternative?lower?level?class?called?"DrlParser"?can?also?be?used
          ????????
          ????????PackageBuilder?builder?
          =?new?PackageBuilder();

          ????????
          //this?wil?parse?and?compile?in?one?step
          ????????
          //NOTE:?There?are?2?methods?here,?the?one?argument?one?is?for?normal?DRL.
          ????????
          //builder.addPackageFromDrl(?source?);

          ????????
          //Use?the?following?instead?of?above?if?you?are?using?a?DSL:
          ????????builder.addPackageFromDrl(?source,?dsl?);
          ????????
          ????????
          //get?the?compiled?package?(which?is?serializable)
          ????????Package?pkg?=?builder.getPackage();
          ????????
          ????????
          //add?the?package?to?a?rulebase?(deploy?the?rule?package).
          ????????RuleBase?ruleBase?=?RuleBaseFactory.newRuleBase();
          ????????ruleBase.addPackage(?pkg?);
          ????????
          return?ruleBase;
          ????}

          這里在官方的例子基礎上做了自己的實現(其實什么都沒改)。

          可以看到,第一步是取得文件IO,這個文件就是我們要寫得規則腳本,這個等下再說,大家可以假象一下腳本是個什么樣子,現在只說怎么在程序中取得Rule。
          接下來,是使用Builder取得一個package,既然builder都上來了說明能輸入的腳本不止一個了。用addPackageFromDrl向這個builder壓縮機里面輸入腳本,當然還有另外一個文件dsl,這個后面再說。利用builder取得package。

          最后構造一個BaseRule,利用Factory取得的時候是有選擇的,RuleBaseFactory.newRuleBase(int type)其中的type可以為不同的Algorithm,有RETE和Leaps 兩種。對這兩種Algorithm的具體解釋可以參看 http://citeseer.ist.psu.edu/context/505087/0?或是 drools的文檔,其實我也不太懂。

          把剛才的package添到ruleBase里面一個Rule就大功告成了。

          接下來看看怎么執行它:
          ????????????WorkingMemory?workingMemory?=?ruleBase.newWorkingMemory();
          ????????????
          ????????????
          //go?!
          ????????????Order?order?=?new?Order();
          ????????????order.setId(
          1);
          ????????????order.setName(
          "testOrder");
          ????????????order.setTotlePrice(
          10);
          ????????????????????????
          ????????????User?user?
          =?new?User();
          ????????????user.setName(
          "testAdmin");
          ????????????user.setAuth(
          "USER_ADMIN");
          ????????????List
          <String>?roles?=?new?ArrayList<String>();
          ????????????roles.add(
          "ADMIN");
          ????????????user.setRoles(roles);
          ????????????

          ????????????User?user1?
          =?new?User();
          ????????????user1.setName(
          "testUser");
          ????????????user1.setAuth(
          "USER_USER");
          ????????????List
          <String>?roles1?=?new?ArrayList<String>();
          ????????????roles1.add(
          "USER");
          ????????????user1.setRoles(roles1);
          ????????????
          ????????????workingMemory.assertObject(order);
          ????????????workingMemory.assertObject(user);
          ????????????workingMemory.assertObject(user1);
          ????????????
          ????????????workingMemory.fireAllRules();????????
          ????????????
          ????????????List
          <AclEntry>?acls?=?workingMemory.getObjects(AclEntry.class);

          用ruleBase生成一個WorkingMemory,WorkingMemory是Rule的執行引擎,裝載rule和事實(很重要的概念),并統一執行他們。接下來我就在寫我的事實,事實是什么,事實就是今天是什么天?訂單總價多少?就是要告訴腳本的java對象。然后把事實一一壓入WorkingMemory這個大壓縮機。就瞧好吧。

          OK可以執行了,fireAllRules!(真TM,COOL的名字)。當然有全部執行就有部分執行。你可以把規則分組,然后按組執行,或是指定rule的名字來執行(這里還是大家自己看看吧)。

          ???究竟執行了什么。當然是執行了我們的腳本,腳本在這里、看看它可不是xml了:
          #created?on:?2006-5-19
          package?com.sample;

          #list?any?
          import?classes?here.

          import?com.sample.domain.Order;
          import?com.sample.domain.User;

          import?com.sample.AclEntry;
          #expander?mylang.dsl

          #declare?any?global?variables?here

          rule?
          "Order?TotlePrice?more?than?$1000"????
          ????when
          ????????#conditions
          ????????$order?:?Order(?totlePrice?
          >?1000?)
          ????????$user?:?User(?roles?contains?
          "ADMIN"?,?$userName?:?name)
          ????then?
          ????????#actions
          ????????System.out.println(
          "More?Than");
          ????????
          assert(new?AclEntry($order,?$user,?1));
          end

          rule?
          "Order?TotlePrice?less?or?equl?than?$1000"????
          ????when
          ????????#conditions
          ????????$order?:?Order(?totlePrice?
          <=?1000?)
          ????????$user?:?User(?$userName?:?name?)
          ????then?
          ????????#actions
          ????????System.out.println(
          "Less?Than");
          ????????
          assert(new?AclEntry($order,?$user,?2));
          end

          每一個rule就是一個規則,所有的事實要一一過一遍這些規則。when是規則提出的條件,如果哪個事實符合這個條件,就進入then的環節,進行相應的處理。

          分析一下條件:$order?:?Order(?totlePrice?>?1000?)。一看就知道是總價超過1000的訂單。$order是把這個訂單邦定,后面可以使用。
          分析一下then:?System.out.println就不解釋了。assert(new?AclEntry($order,?$user,?2)); 這里的assert的意義就是告訴WorkingMemory一個事實,其實跟前面的加入事實一個道理。打個比方,如果有閃電,那么就有雷。

          這樣走完一個rule后大家很容易發現,其實是根據訂單和用戶的角色不同產生了不同的acl,然后我要拿到這些由事實得到的事實。

          List<AclEntry>?acls?=?workingMemory.getObjects(AclEntry.class);
          這樣就能在workingMemory里面掏出我們需要的事實來,新鮮出爐的哦。

          相當粗略的講了一下drools,目的是希望大家都來了解一下,共同學習。
          posted @ 2006-05-28 20:53 差沙 閱讀(2839) | 評論 (9)編輯 收藏

          以前不寫blog,很多技術學完就忘了。總是反復請教google,慚愧的很。決心以后記錄自己技術的點點滴滴了。

          posted @ 2006-05-27 22:52 差沙 閱讀(472) | 評論 (0)編輯 收藏
          僅列出標題
          共2頁: 上一頁 1 2 
          這家伙很懶,但起碼還是寫了一句話。

          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(8)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 航空| 龙胜| 南丰县| 新巴尔虎右旗| 溧水县| 广平县| 西充县| 乌鲁木齐县| 福泉市| 哈密市| 泾川县| 互助| 威远县| 英德市| 绥宁县| 闽清县| 靖安县| 镇宁| 南江县| 烟台市| 六盘水市| 齐河县| 永清县| 柳州市| 怀安县| 监利县| 青州市| 永善县| 肥乡县| 恩施市| 甘谷县| 绍兴市| 宣恩县| 永兴县| 宜川县| 扎囊县| 开江县| 万源市| 安化县| 洞口县| 西丰县|