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

          首先要理解Acegi里面Voter的概念,ACL正是在一個(gè)Voter上擴(kuò)展起來的。現(xiàn)來看一下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指的是這個(gè)Voter對哪些SecurityConfig起作用,我們可以把ACL_READ配置在想要攔截的Method上。比方說我們要攔截readOrder這個(gè)方法,以實(shí)現(xiàn)ACL控制,可以這樣配置。
            orderManager.readOrder=ACL_READ
          2. processDomainObjectClass指出哪些DomainObject是要進(jìn)行ACL校驗(yàn)的。
          3. aclManager是一個(gè)比較重要的概念,主要負(fù)責(zé)在權(quán)限列表中根據(jù)用戶和DomainObject取得acl列表。
          4. requirePermission指出要進(jìn)行這個(gè)操作必須具備的acl權(quán)限,比方說read操作就必須有ADMINISTRATION或READ兩個(gè)權(quán)限。

          其實(shí)整個(gè)過程看下來比較清晰,下面來看一下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的一貫風(fēng)格,Provider可以提供多種取得ACL訪問列表的途徑,默認(rèn)的是用basicAclProvider在數(shù)據(jù)庫中取得。既然提到了數(shù)據(jù)庫,那我們就來看一下Acegi默認(rèn)提供的ACL在數(shù)據(jù)庫里的保存表結(jié)構(gòu):

          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表存放了所有受保護(hù)的domainObject的信息。其中object_identity字段保存了domainObject的class和id,默認(rèn)的保存格式是:domainClass:domainObjectId。
          2. acl_permission?就是ACL權(quán)限列表了,recipient?是用戶或角色信息,mask表示了這個(gè)用戶或角色對這個(gè)domainObject的訪問權(quán)限。注意這些信息的保存格式都是可以根據(jù)自己的需要改變的。

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

          ????<!--?==============?"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會在攔截的方法執(zhí)行結(jié)束的時(shí)候執(zhí)行。主要的作用就是在返回的List中挨個(gè)檢查domainObject的操作權(quán)限,然后根據(jù)requirePermission來剔除不符合的domainObject。
          posted @ 2006-06-17 00:20 差沙 閱讀(2283) | 評論 (4)編輯 收藏
          acegi1.0發(fā)布,其實(shí)有點(diǎn)出乎意料,因?yàn)槲乙幌蛘J(rèn)為acegi的代碼已經(jīng)相當(dāng)穩(wěn)定了,但是acegi力求精益求精,從新版還是能看到不少實(shí)用的改動和升級。這里簡單分析一下。

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

          以前如果使用HttpSessionContextIntegrationFilter的話,不管你是否需要?jiǎng)?chuàng)建session,他都會給你創(chuàng)建。這在一些Base驗(yàn)證的時(shí)候是多余的。現(xiàn)在加上了forceEagerSessionCreation,在創(chuàng)建session的時(shí)候做了控制。

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

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

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

          [SEC-92] - Hibernate ACL implementation

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

          [SEC-147] - BasicAclEntryAfterInvocationProvider should support processDomainObjectClass

          對List進(jìn)行ACL交驗(yàn)的時(shí)候,會把第一個(gè)元素取出,看看是否AssignableFrom這個(gè)processDomainObjectClass ,算是做一下安全檢查吧。

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

          其實(shí)應(yīng)該是不允許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 時(shí)候會更加靈活了,得益于spring的強(qiáng)大。

          <明天繼續(xù)吧。。。。>

          [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 差沙 閱讀(563) | 評論 (0)編輯 收藏
          這兩天在springside受白衣的影響開始關(guān)注drools。說他是平民的腳本引擎一點(diǎn)都不假,使用起來極為方便,本來以為網(wǎng)上應(yīng)該有不少的講解了,但是發(fā)現(xiàn)幾乎全是針對2.0版本講解的。而drools加入jboss后有了質(zhì)的變化,下面來看一下最新的3.0使用起來有什么不同:

          首先我們要取得rule,規(guī)則引擎、規(guī)則引擎,取得規(guī)則是必要的。
          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;
          ????}

          這里在官方的例子基礎(chǔ)上做了自己的實(shí)現(xiàn)(其實(shí)什么都沒改)。

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

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

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

          接下來看看怎么執(zhí)行它:
          ????????????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生成一個(gè)WorkingMemory,WorkingMemory是Rule的執(zhí)行引擎,裝載rule和事實(shí)(很重要的概念),并統(tǒng)一執(zhí)行他們。接下來我就在寫我的事實(shí),事實(shí)是什么,事實(shí)就是今天是什么天?訂單總價(jià)多少?就是要告訴腳本的java對象。然后把事實(shí)一一壓入WorkingMemory這個(gè)大壓縮機(jī)。就瞧好吧。

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

          ???究竟執(zhí)行了什么。當(dāng)然是執(zhí)行了我們的腳本,腳本在這里、看看它可不是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

          每一個(gè)rule就是一個(gè)規(guī)則,所有的事實(shí)要一一過一遍這些規(guī)則。when是規(guī)則提出的條件,如果哪個(gè)事實(shí)符合這個(gè)條件,就進(jìn)入then的環(huán)節(jié),進(jìn)行相應(yīng)的處理。

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

          這樣走完一個(gè)rule后大家很容易發(fā)現(xiàn),其實(shí)是根據(jù)訂單和用戶的角色不同產(chǎn)生了不同的acl,然后我要拿到這些由事實(shí)得到的事實(shí)。

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

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

          以前不寫blog,很多技術(shù)學(xué)完就忘了。總是反復(fù)請教google,慚愧的很。決心以后記錄自己技術(shù)的點(diǎn)點(diǎn)滴滴了。

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

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(8)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 南江县| 垣曲县| 舒兰市| 兰西县| 山西省| 定日县| 屏南县| 萨迦县| 海盐县| 四会市| 五峰| 建瓯市| 大英县| 东光县| 手游| 松溪县| 扎兰屯市| 鄂尔多斯市| 珠海市| 张掖市| 福海县| 四子王旗| 忻州市| 开远市| 信丰县| 宿迁市| 临安市| 鸡泽县| 买车| 双辽市| 镇远县| 兴安盟| 罗江县| 双城市| 五峰| 平泉县| 康平县| 嫩江县| 禹城市| 马龙县| 禄劝|