Sealyu

          --- 博客已遷移至: http://www.sealyu.com/blog

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks
          <2010年1月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(14)

          隨筆分類

          隨筆檔案

          友情鏈接

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          在SpringSide 3的官方文檔中,說(shuō)安全框架使用的是Spring Security 2.0。乍一看,嚇了我一跳,以為Acegi這么快就被淘汰了呢。上搜索引擎一搜,發(fā)現(xiàn)原來(lái)Spring Security 2.0就是Acegi 2.0。懸著的心放下來(lái)了。雖然SpringSide 3中關(guān)于Acegi的配置文件看起來(lái)很不熟悉,但是讀了Acegi 2.0的官方文檔后,一切都釋然了。

          先來(lái)談一談Acegi的基礎(chǔ)知識(shí),Acegi的架構(gòu)比較復(fù)雜,但是我希望我下面的只言片語(yǔ)能夠把它說(shuō) 清楚。大家都知道,如果要對(duì)Web資源進(jìn)行保護(hù),最好的辦法莫過(guò)于Filter,要想對(duì)方法調(diào)用進(jìn)行保護(hù),最好的辦法莫過(guò)于AOP。Acegi對(duì)Web資 源的保護(hù),就是靠Filter實(shí)現(xiàn)的。如下圖:
          001.PNG

          一 般來(lái)說(shuō),我們的Filter都是配置在web.xml中,但是Acegi不一樣,它在web.xml中配置的只是一個(gè)代理,而真正起作用的Filter是 作為Bean配置在Spring中的。web.xml中的代理依次調(diào)用這些Bean,就實(shí)現(xiàn)了對(duì)Web資源的保護(hù),同時(shí)這些Filter作為Bean被 Spring管理,所以實(shí)現(xiàn)AOP也很簡(jiǎn)單,真的是一舉兩得啊。

          Acegi中提供的Filter不少,有十多個(gè),一個(gè)一個(gè)學(xué)起來(lái)比較復(fù)雜。但是對(duì)于我們Web開發(fā)者來(lái)說(shuō),常用的就那么幾個(gè),如下圖中的被紅圈圈標(biāo)記出來(lái)的:
          002.PNG

          從上到下,它們實(shí)現(xiàn)的功能依次是1、制定必須為https連接;2、從Session中提取用戶的認(rèn)證信息;3、退出登錄;4、登錄;5、記住用戶;6、所有的應(yīng)用必須配置這個(gè)Filter。

          一 般來(lái)說(shuō),我們寫Web應(yīng)用只需要熟悉這幾個(gè)Filter就可以了,如果不需要https連接,連第一個(gè)也不用熟悉。但是有人肯定會(huì)想,這些Filter怎 么和我的數(shù)據(jù)庫(kù)聯(lián)系起來(lái)呢?不用著急,這些Filter并不直接處理用戶的認(rèn)證,也不直接處理用戶的授權(quán),而是把它們交給了認(rèn)證管理器和決策管理器。如下 圖:
          003.PNG

          對(duì)于這兩種管理器,那也是不需要我們寫代碼的,Acegi也提供了現(xiàn)成的類。那么大家又奇怪了:又是現(xiàn)成的,那怎么和我的數(shù)據(jù)庫(kù)關(guān)聯(lián)起來(lái)呢?別著急,其實(shí)這兩個(gè)管理器自己也不做事,認(rèn)證管理器把任務(wù)交給了Provider,而決策管理器則把任務(wù)交給了Voter,如下圖:
          004.PNG

          現(xiàn) 在我要告訴你們,這里的Provider和Voter也是不需要我們寫代碼的。不要崩潰,快到目標(biāo)了。Acegi提供了多個(gè)Provider的實(shí)現(xiàn)類,如 果我們想用數(shù)據(jù)庫(kù)來(lái)儲(chǔ)存用戶的認(rèn)證數(shù)據(jù),那么我們就選擇DaoAuthenticationProvider。對(duì)于Voter,我們一般選擇 RoleVoter就夠用了,它會(huì)根據(jù)我們配置文件中的設(shè)置來(lái)決定是否允許某一個(gè)用戶訪問(wèn)制定的Web資源。

          而DaoAuthenticationProvider也是不直接操作數(shù)據(jù)庫(kù)的,它把任務(wù)委托給了UserDetailService,如下圖:
          005.PNG

          而 我們要做的,就是實(shí)現(xiàn)這個(gè)UserDetailService。圖畫得不好,大家不要見(jiàn)笑,但是說(shuō)了這么多總算是引出了我們開發(fā)中的關(guān)鍵,那就是我們要實(shí) 現(xiàn)自己的UserDetailService,它就是連接我們的數(shù)據(jù)庫(kù)和Acegi的橋梁。UserDetailService的要求也很簡(jiǎn)單,只需要一 個(gè)返回org.springframework.security.userdetails.User對(duì)象的 loadUserByUsername(String userName)方法。因此,怎么設(shè)計(jì)數(shù)據(jù)庫(kù)都可以,不管我們是用一個(gè)表還是兩個(gè)表還是三個(gè)表,也不管我們是用戶-授權(quán),還是用戶-角色-授權(quán),還是用 戶-用戶組-角色-授權(quán),這些具體的東西Acegi統(tǒng)統(tǒng)不關(guān)心,它只關(guān)心返回的那個(gè)User對(duì)象,至于怎么從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),那就是我們自己的事了。

          反 過(guò)來(lái)再看看上面的過(guò)程,我們發(fā)現(xiàn),即使我們要做的只是實(shí)現(xiàn)自己的UserDetailService類,但是我們不得不在Spring中配置那一大堆的 Bean,包括幾個(gè)Filter,幾個(gè)Manager,幾個(gè)Provider和Voter,而這些配置往往都是重復(fù)的無(wú)謂的。好在Acegi 2.0也認(rèn)識(shí)到了這個(gè)問(wèn)題,所以,它設(shè)計(jì)了一個(gè)<http>標(biāo)簽,讓Acegi的配置得到了簡(jiǎn)化。下面是SpringSide 3中的配置的截圖,大家可以看看:
          006.PNG

          下圖是官方文章中的傳統(tǒng)Filter設(shè)置和<http>元素之間的對(duì)應(yīng)關(guān)系:
          007.PNG

          下 面的代碼是SpringSide 3中實(shí)現(xiàn)UserDetailService的范例,在SpringSide 3的范例中,白衣使用了三個(gè)表User、Role、Authority。但是Acegi不關(guān)心你用了幾個(gè)表,它只關(guān)心UserDetails對(duì)象。而決定 用戶能否訪問(wèn)指定Web資源的,是RoleVoter類,無(wú)需任何修改它可以工作得很好,唯一的缺點(diǎn)是它只認(rèn)ROLE_前綴,所以搞得白衣的 Authority看起來(lái)都象角色,不倫不類。

          package  personal.youxia.service.security;

          import  java.util.ArrayList;
          import  java.util.List;

          import  org.springframework.beans.factory.annotation.Required;
          import  org.springframework.dao.DataAccessException;
          import  org.springframework.security.GrantedAuthority;
          import  org.springframework.security.GrantedAuthorityImpl;
          import  org.springframework.security.userdetails.UserDetails;
          import  org.springframework.security.userdetails.UserDetailsService;
          import  org.springframework.security.userdetails.UsernameNotFoundException;
          import  personal.youxia.entity.user.Authority;
          import  personal.youxia.entity.user.Role;
          import  personal.youxia.entity.user.User;
          import  personal.youxia.service.user.UserManager;

          /**
           * 實(shí)現(xiàn)SpringSecurity的UserDetailsService接口,獲取用戶Detail信息.
           * 
           * 
          @author  calvin
           
          */
          public   class  UserDetailServiceImpl  implements  UserDetailsService {

              
          private  UserManager userManager;

              
          public  UserDetails loadUserByUsername(String userName)  throws  UsernameNotFoundException, DataAccessException {
                  User user 
          =  userManager.getUserByLoginName(userName);
                  
          if  (user  ==   null )
                      
          throw   new  UsernameNotFoundException(userName  +   "  不存在 " );

                  List
          < GrantedAuthority >  authsList  =   new  ArrayList < GrantedAuthority > ();

                  
          for  (Role role : user.getRoles()) {
                      
          for  (Authority authority : role.getAuths()) {
                          authsList.add(
          new  GrantedAuthorityImpl(authority.getName()));
                      }
                  }

                  
          //  目前在MultiDatabaseExample的User類中沒(méi)有enabled, accountNonExpired,credentialsNonExpired, accountNonLocked等屬性
                  
          //  暫時(shí)全部設(shè)為true,在需要時(shí)才添加這些屬性.
                  org.springframework.security.userdetails.User userdetail  =   new  org.springframework.security.userdetails.User(
                          user.getLoginName(), user.getPassword(), 
          true true true true , authsList
                                  .toArray(
          new  GrantedAuthority[authsList.size()]));

                  
          return  userdetail;
              }

              @Required
              
          public   void  setUserManager(UserManager userManager) {
                  
          this .userManager  =  userManager;
              }
          }


          最 后再來(lái)說(shuō)說(shuō)這個(gè)命名的問(wèn)題,我對(duì)Authentication和Authority這兩個(gè)單詞比較反感,兩個(gè)原因,一是因?yàn)樗鼈兲Я耍且驗(yàn)樗鼈冮L(zhǎng) 得太像了,明明一個(gè)是認(rèn)證,一個(gè)是授權(quán),意思相差很遠(yuǎn),外貌卻如此相似,確實(shí)很煩人。如果讓我來(lái)選擇,我喜歡Privilege這個(gè)單詞,在我剛使用 MySQL的時(shí)候就跟它很熟了,所以在我的項(xiàng)目中,我可能會(huì)用Privilege來(lái)代替Authority。如果我們只使用User-Role兩級(jí)關(guān)系, 使用RoleVoter默認(rèn)的ROLE_前綴當(dāng)然沒(méi)有關(guān)系,如果是像白衣這樣是用三層關(guān)系,最好還是把這個(gè)前綴改一改,以免混淆。
          posted on 2010-01-08 17:01 seal 閱讀(350) 評(píng)論(1)  編輯  收藏 所屬分類: Spring

          評(píng)論

          # re: SpringSide 3 中的安全框架 2010-01-09 11:37 ipKim
          Yeah indeed very
          fortunate for the lector it was pleasant to read about this good topic! If you need to get a great job firstofall you need <a href="http://www.prime-resume.com">resume service</a>. Study and don't forget - if you have to work and study at the same time, there arehotshots who are ready to aid you with your resume when you under time heaviness and looking for a great job.  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 大足县| 道真| 渝北区| 木兰县| 望奎县| 华池县| 永丰县| 微山县| 中方县| 永川市| 盈江县| 宝鸡市| 壤塘县| 云南省| 商水县| 吉林省| 泽州县| 肥乡县| 海原县| 万州区| 乌兰浩特市| 迁安市| 独山县| 华安县| 澄城县| 敦化市| 行唐县| 湖北省| 民乐县| 铜陵市| 三原县| 岳普湖县| 荔浦县| 额敏县| 大丰市| 岳池县| 萨嘎县| 金平| 清水县| 西宁市| 会东县|