每日一得

          不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發(fā)
          最近關(guān)心的內(nèi)容:SSH,seam,flex,敏捷,TDD
          本站的官方站點(diǎn)是:顛覆軟件

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks

          3? Jive 安全管理機(jī)制

          Jive 中除了前面介紹的有關(guān)設(shè)計(jì)模式實(shí)現(xiàn)組件外,還有其他有一定特點(diǎn)的組件功能,分析研究這些組件功能可以更加完整透徹地理解 Jive 論壇系統(tǒng)。

          Jive 安全管理機(jī)制基本是由下列部分組成:

          ·????????? 安全驗(yàn)證機(jī)制。主要是驗(yàn)證用戶名和密碼組合是否與數(shù)據(jù)庫中注冊時(shí)的數(shù)據(jù)一致,以確認(rèn)該用戶身份為注冊用戶。這是對所有的 JSP 訪問都進(jìn)行攔截訪問。

          ·????????? 訪問權(quán)限控制( ACL )。對不同的數(shù)據(jù)不同用戶擁有不同的訪問權(quán)限,例如,一個(gè)帖子普通用戶可以瀏覽,但是不能更該;但是管理員卻可以編輯刪除。這部分功能是通過代理模式實(shí)現(xiàn),為每個(gè)關(guān)鍵數(shù)據(jù)都建立一個(gè)代理類用來實(shí)現(xiàn)訪問權(quán)限檢查,這在前面討論過。

          ·????????? 用戶資料管理系統(tǒng)。主要是管理用戶的資料數(shù)據(jù),進(jìn)行用戶組和用戶關(guān)系的建立等。

          1? 安全驗(yàn)證機(jī)制

          Jive 的安全驗(yàn)證機(jī)制是按照比較通用的思路設(shè)計(jì)的。類似前面“簡單的用戶注冊管理系統(tǒng)”中的介紹, Jive 也是在所有的 JSP 頁面中 include 一個(gè)安全檢驗(yàn)功能的 global.jsp 。由于 global.jsp 是在每個(gè) JSP 一開始必須執(zhí)行的功能,因此通過攔截 global.jsp 攔截發(fā)往各個(gè) JSP 頁面的請求( request )。如果這個(gè)請求是合法的,將被允許通過;如果不是,將注明請求者身份是 Anonymous (匿名者)。

          global.jsp 代碼如下:

          boolean isGuest = false;

          Authorization authToken = SkinUtils.getUserAuthorization(request, response);

          if (authToken == null) {// 未被驗(yàn)證通過

          ??? authToken = AuthorizationFactory.getAnonymousAuthorization();

          ??? isGuest=true;

          }

          Jive 中,以 Authorization 對象作為驗(yàn)證通過的標(biāo)志,它的接口代碼如下:

          public interface Authorization {

          ??? public long getUserID();???

          ??? public boolean isAnonymous();

          }

          具體實(shí)現(xiàn)是 DbAuthorization ,代碼如下:

          public final class DbAuthorization implements Authorization, Serializable {

          ??? private long userID;

          ??? protected DbAuthorization(long userID) {

          ??????? this.userID = userID;

          ??? }

          ??? public long getUserID() {

          ??????? return userID;

          ??? }

          ??? public boolean isAnonymous() {

          ??????? return userID == -1;

          ??? }

          }

          此類只是一個(gè) userID ,因此只是一個(gè)象征性的標(biāo)志。

          SkinUtils 是一個(gè)為 JSP 服務(wù)的類,它的 getUserAuthorization 代碼如下:

          public static Authorization getUserAuthorization

          ??????? (HttpServletRequest request, HttpServletResponse response)

          ? {

          ??? HttpSession session = request.getSession();

          ??? // HttpSession 中獲取 Authorization 實(shí)例

          ??? Authorization authToken =

          (Authorization)session.getAttribute(JIVE_AUTH_TOKEN);

          ??? if (authToken != null) {???? return authToken;? }

          ?

          ??? // 如果 HttpSession 中沒有,檢查用戶瀏覽器 cookie

          ??? Cookie cookie = getCookie(request, JIVE_AUTOLOGIN_COOKIE);

          ??? if (cookie != null) {

          ??????? try {

          ?????????? String[] values = decodePasswordCookie(cookie.getValue());

          ?????????? String username = values[0];

          ?????????? String password = values[1];

          ?????????? // cookie 中獲得用戶名和密碼后,進(jìn)行安全驗(yàn)證

          ?????????? authToken = AuthorizationFactory.getAuthorization(username,password);

          ??????? }catch (Exception e) {}

          ??????? // put that token in the user's session:

          ??????? if (authToken != null) {// 如果通過驗(yàn)證,保存 authToken http Session

          ?????????? session.setAttribute(JIVE_AUTH_TOKEN, authToken);

          ??????? }

          ?????? // return the authorization token

          ??????? return authToken;

          ??? }

          ? ??return null;

          }

          用戶驗(yàn)證預(yù)先通過兩個(gè)步驟。首先檢查 HttpSession 中是否保存了該用戶的驗(yàn)證信息,如果用戶第一次驗(yàn)證通過,反復(fù)訪問,這道關(guān)口檢查就可以通過。

          如果 HttpSession 中沒有驗(yàn)證信息,那么從該用戶的瀏覽器 cookie 中尋找用戶名和密碼。如果該用戶激活了 cookie 保存這些登錄信息,那么應(yīng)該可以找到用戶名和密碼,這樣就省卻了用戶再次從鍵盤輸入用戶名和密碼,將用戶名和密碼通過下列語句進(jìn)行數(shù)據(jù)庫驗(yàn)證:

          authToken = AuthorizationFactory.getAuthorization(username,password);

          這一舉是驗(yàn)證關(guān)鍵。 AuthorizationFactory 是一個(gè)抽象類,定義了 Jive 安全驗(yàn)證機(jī)制所需的所有方法, AuthorizationFactory 的實(shí)現(xiàn)類似前面討論的 ForumFactory 實(shí)現(xiàn),是使用工廠模式加動態(tài)類反射機(jī)制完成的,代碼如下:

          public abstract class AuthorizationFactory {

          ?? // 定義一個(gè)數(shù)據(jù)庫具體實(shí)現(xiàn)

          ??? private static String className =

          ??????? " com.Yasna.forum.database.DbAuthorizationFactory";

          ?

          ??? private static AuthorizationFactory factory = null;

          ??? // 驗(yàn)證方法 如果沒有 UnauthorizedException 拋出,表示驗(yàn)證通過

          ??? public static Authorization getAuthorization(String username,

          ??????????? String password) throws UnauthorizedException

          ??? {

          ??????? loadAuthorizationFactory();

          ??????? return factory.createAuthorization(username, password);

          ??? }

          ??? // 匿名者處理方法

          ??? public static Authorization getAnonymousAuthorization() {

          ??????? loadAuthorizationFactory();

          ??????? return factory.createAnonymousAuthorization();

          ??? }

          ??? // 需要具體實(shí)現(xiàn)的抽象方法

          ??? protected abstract Authorization createAuthorization(String username,

          ??????????? String password) throws UnauthorizedException;

          ??? protected abstract Authorization createAnonymousAuthorization();

          ??? // 動態(tài)配置 AuthorizationFactory 的具體實(shí)現(xiàn),可以在配置文件中定義一個(gè)

          ??? // 基于 LDAP 的實(shí)現(xiàn)。類似 ForumFactory getInstance 方法

          ??? private static void loadAuthorizationFactory() {

          ??????? …

          ??? }

          }

          AuthorizationFactory 看上去很復(fù)雜,實(shí)際只有一個(gè)核心方法 getAuthorization 。實(shí)現(xiàn)用戶名和密碼的驗(yàn)證。如果無法通過驗(yàn)證,有兩個(gè)信息實(shí)現(xiàn)顯示:一個(gè)是拋出 UnauthorizedException ,另外一個(gè)是返回空的 Authorization 對象。

          那么,子類 DbAuthorizationFactory 毫無疑問就是查詢數(shù)據(jù)庫,將輸入的用戶名和密碼與數(shù)據(jù)庫保存的用戶名和密碼進(jìn)行校驗(yàn)。

          Jive 的安全驗(yàn)證機(jī)制比較簡單易懂,值得在實(shí)踐中學(xué)習(xí)借鑒。但是注意到這套安全驗(yàn)證機(jī)制只是 Web 層的“手工”驗(yàn)證,資源訪問權(quán)限( ACL )也是自己“手工”來實(shí)現(xiàn)的。如果使用 EJB 技術(shù),因?yàn)?/span> EJB 容器本身有一定的資源訪問控制體系,因此在 Web 層驗(yàn)證通過后,需要將這些登錄信息傳遞到 EJB 層。當(dāng)然如果直接使用 Web 容器的安全驗(yàn)證機(jī)制,那么 Web 層與 EJB 層之間的登錄信息傳遞將由容器實(shí)現(xiàn),這樣就更加簡單方便。

          Jive 這種的安全驗(yàn)證并不是使用 Web 容器的安全驗(yàn)證機(jī)制,如何使用 Web 容器的安全驗(yàn)證機(jī)制將在以后章節(jié)介紹。盡管如此, Jive 這套安全驗(yàn)證機(jī)制對付小型系統(tǒng)的應(yīng)用也是足夠的。


          2? 用戶資料管理

          Jive 中,用戶 User 對象的操作訪問類似于論壇 Forum 對象的訪問,與 User 對象有關(guān)的操作都封裝在一個(gè)類中操作,這是外觀( Facade )模式的應(yīng)用。

          Jive 中,用戶資料管理屬于大系統(tǒng)中的一個(gè)子系統(tǒng),在這個(gè)子系統(tǒng)中,用戶子系統(tǒng)和其他系統(tǒng)又有一定的關(guān)系,涉及的類不少,通過建立一個(gè) UserManager 類來統(tǒng)一對外接口,使得整個(gè)子系統(tǒng)條目結(jié)構(gòu)清晰。

          UserManager 中無外乎用戶數(shù)據(jù)的管理,如用戶的創(chuàng)建、修改、查詢和刪除。 DbUserManager UserManager 的一個(gè)數(shù)據(jù)庫實(shí)現(xiàn),可是看看 DbUserManager 中除了刪除功能是直接通過 SQL 語句進(jìn)行數(shù)據(jù)庫刪除操作外,其他都委托給 User 的具體實(shí)現(xiàn) DbUser 實(shí)現(xiàn)的。這種實(shí)現(xiàn)非常類似于 EJB Session Bean 和實(shí)體 Bean 之間的關(guān)系。以創(chuàng)建用戶資料為例,代碼如下:

          public User createUser(String username, String password, String email)

          ??????????? throws UserAlreadyExistsException

          ?{

          ??????? User newUser = null;

          ??????? try {

          ??????????? // username 查詢改用戶是否存在

          ??????????? User existingUser = getUser(username);

          ??????????? // 如果沒有拋出 UserNotFoundException 異常,表示該用戶存在

          ??????????? //The user already exists since now exception, so:

          ??????????? throw new UserAlreadyExistsException();

          ??????? } catch (UserNotFoundException unfe) {

          ??????????? // 該用戶不存在,創(chuàng)建一個(gè)新用戶

          ??????????? newUser = new DbUser(username, password, email, factory);

          ??????? }

          ??????? return newUser;

          }

          DbUser 的構(gòu)造方法實(shí)際是用戶資料的新增創(chuàng)建:

          protected DbUser(String username, String password, String email,

          ??????????? DbForumFactory factory)

          {

          ??????? this.id = SequenceManager.nextID(JiveGlobals.USER);? // 獲得自增 ID

          ??????? this.username = username;

          ??????? // Compute hash of password.

          ??? ????this.passwordHash = StringUtils.hash(password);? // 獲得加密的密碼

          ??????? this.email = email;

          ??????? this.factory = factory;

          ??????? long now = System.currentTimeMillis();

          ??????? creationDate = new java.util.Date(now);

          ??????? modifiedDate = new java.util.Date(now);

          ??????? properties = new Hashtable();

          ??????? insertIntoDb();????????????? // 數(shù)據(jù)庫插入數(shù)據(jù)

          }

          Jive 中,數(shù)據(jù)修改的保存是由 DbUser saveToDb 方法實(shí)現(xiàn)的,而 saveToDb 方法調(diào)用是在每個(gè) setXXXX 方法中。即每當(dāng)外界調(diào)用 DbUser setXXXX ,則表示需要改變某些字段屬性值,在這個(gè)方法中直接進(jìn)行數(shù)據(jù)庫存儲,這也類似 EJB CMP 實(shí)體 Bean 的數(shù)據(jù)字段修改保存。

          Jive 中組 Group 與用戶 User 處理幾乎差不多,只是在 Group 中整合了權(quán)限方面的信息,這種做法是有一定的局限性,不是很值得借鑒,要想設(shè)計(jì)一個(gè)動態(tài)擴(kuò)展靈活的權(quán)限系統(tǒng),必須在用戶或組與權(quán)限之間引入角色概念,也就是比較先進(jìn)的基于角色的權(quán)限系統(tǒng)( RBAC Roled-Based Access Control ,相關(guān)網(wǎng)址: http://csrc.nist.gov/rbac/ )。

          RBAC 中,用戶組只是用戶的一個(gè)集合,應(yīng)該是通過角色和權(quán)限發(fā)生聯(lián)系。所以 RBAC 認(rèn)為,如果給用戶組賦予權(quán)限,那么用戶組也接近角色的概念。

          posted on 2006-08-31 12:26 Alex 閱讀(698) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 金山区| 东阿县| 新昌县| 嵊州市| 兴安县| 屏南县| 闽清县| 叶城县| 宜都市| 永登县| 龙门县| 广河县| 嫩江县| 吉首市| 仁化县| 湛江市| 银川市| 洮南市| 仁布县| 雷波县| 筠连县| 定襄县| 翼城县| 托克托县| 长岛县| 阜新市| 房产| 云梦县| 西乌珠穆沁旗| 宁乡县| 永春县| 旅游| 平阴县| 杭锦后旗| 江川县| 迁西县| 勐海县| 邯郸市| 潜山县| 博湖县| 红桥区|