nighty

          折騰的年華
          posts - 37, comments - 143, trackbacks - 0, articles - 0

          JForum集成--用戶重名的一種解決方案

          Posted on 2009-10-14 17:41 寒武紀 閱讀(2179) 評論(1)  編輯  收藏 所屬分類: 系統集成
               JForum做為一個成熟的開源BBS論壇解決方案,提供了非常方便的SSO集成接口。它的主頁上和網上都有許多介紹如何用SSO方式進行集成的辦法。這里不羅列,google可以找到許多資料,主要描述一下如何解決用戶名重名的一種方式。目前使用的JForum版本是2.1.8

               簡單地介紹一下采用的SSO方式。由于應用上需要一個BBS,找了JForum做為一個子系統,集成到現成的一個管理系統當中,管理系統本身有一套完全的身份權限認證方案,由于系統的安全要求不是特別嚴格,所以采了最直接和最省事的方式:Cookie寫入。即在管理系統登錄時,把用戶信息寫入Cookie,JForum從Cookie中讀取用戶信息進行登錄。
               為JForum項目添加一個SSO接口的擴展類CookieSSO,主要實現authenticateUser(RequestContext request)方法。方法大體如下:
              
          public String authenticateUser(RequestContext request) {
                  String userId 
          = null;
                  Cookie c 
          = ControllerUtils.getCookie("ehrbbsuserid");
                  
          if(c!=null){
                      userId 
          = c.getValue();
                  }

                  logger.info(
          "單點登錄BBS用戶ID為:" + userId);
                  
          return userId;
              }
              就是從Cookie中讀取在管理系統中放入的username。但是這里寫的是:ehrbbsuserid,主要是這個變量名來區分傳過來的內容的不同。

              按照正常的方式就是從管理系統把一個用戶的username傳過來。然后在這里取出,return給調用方法進行驗證。在實際項目中,問題就出在這里了
               舉例說有二個用戶名字都叫:李四,那么當二個李四都同時登錄時,JForum的驗證方式就會出問題!它認不清到底是哪個李四,數據庫查詢時只按第一個來!
               仔細看一下jforum的數據庫表設計,jforum_user這個表沒有display_user_name類似的字段,它就是把username做為顯示在頁面上的用戶名,如果不做集成,把它單獨做為一個BBS時,username既是登錄的用戶名,也是顯示在頁面上的用戶名。主要原因我想大概就是老外的思維方式跟中國人的不太一樣。中國人登錄的時候用英文,顯示的時候還有一個昵稱或是中文名等。
               所以把它集成的時候,用Cookie傳送一個username給JForum時就得用中文(而且重名的概率很大)。我們再跟進一個它的代碼,看是誰調用了SSO接口的這個方法:
              結果發現是類:net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法
             
          /**
               * Checks for user authentication using some SSO implementation
               * 
          @param userSession UserSession
               
          */

              
          protected void checkSSO(UserSession userSession)
              
          {
                  
          try {
                      SSO sso 
          = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
                      String username 
          = sso.authenticateUser(JForumExecutionContext.getRequest());

                      
          if (username == null || username.trim().equals("")) {
                          userSession.makeAnonymous();
                      }

                      
          else {
                          SSOUtils utils 
          = new SSOUtils();

                          
          if (!utils.userExists(username)) {
                              SessionContext session 
          = JForumExecutionContext.getRequest().getSessionContext();

                              String email 
          = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
                              String password 
          = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));

                              
          if (email == null{
                                  email 
          = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
                              }


                              
          if (password == null{
                                  password 
          = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
                              }


                              utils.register(password, email);
                          }


                          
          this.configureUserSession(userSession, utils.getUser());
                      }

                  }

                  
          catch (Exception e) {
                      e.printStackTrace();
                      
          throw new ForumException("Error while executing SSO actions: " + e);
                  }

              }
               在這里明顯的,它是通過username去確定這個人是否存在?再繼續跟進代碼就會發現最后調用了Dao的selectUserByName方法。

               解決的思路:修改JForum的數據庫表,并更改代碼和頁面文件是不科學的,工作量大,而且風險比較高!那么就繼續把username用來保存中文名稱,它的user_id是一個自增的數字序列。在管理系統的用戶表中,擴展一個字段bbs_user_id,用來保存在JForum中的用戶id,這個字段就肯定是唯一的,在管理系統登錄時,把這個bbs_user_id查詢出來,放到Cookie中。在JForum驗證時,不再使用它推薦的返回username方式,而是返回它的user_id值。
               那么回到最上面的CookieSSO類的代碼,這里返回的String其實是jforum_user表中user_id字段。為了匹配,那么net.jforum.ControllerUtils的checkSSO(UserSession userSession)方法也要改!改為下面的方式:
            
          protected void checkSSO(UserSession userSession)
              
          {
                  
          try {
                      SSO sso 
          = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
                      String username 
          = sso.authenticateUser(JForumExecutionContext.getRequest());

                      
          if (username == null || username.trim().equals("")) {
                          userSession.makeAnonymous();
                      }

                      
          else {
          //                SSOUtils utils = new SSOUtils();
                          /* 重構為按userId驗證身份 */
          //                if (!utils.userExists(username)) {
          //                    SessionContext session = JForumExecutionContext.getRequest().getSessionContext();
          //
          //                    String email = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_EMAIL_ATTRIBUTE));
          //                    String password = (String) session.getAttribute(SystemGlobals.getValue(ConfigKeys.SSO_PASSWORD_ATTRIBUTE));
          //
          //                    if (email == null) {
          //                        email = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_EMAIL);
          //                    }
          //
          //                    if (password == null) {
          //                        password = SystemGlobals.getValue(ConfigKeys.SSO_DEFAULT_PASSWORD);
          //                    }
          //
          //                    utils.register(password, email);
          //                }
                          /* 新添加的代碼 */
                          UserDAO dao 
          = DataAccessDriver.getInstance().newUserDAO();
                          User user 
          = dao.selectById(Integer.parseInt(username));
                          
          //                this.configureUserSession(userSession, utils.getUser());
                          this.configureUserSession(userSession, user);
                      }

                  }

                  
          catch (Exception e) {
                      e.printStackTrace();
                      
          throw new ForumException("Error while executing SSO actions: " + e);
                  }

              }

              這樣就可以解決認證的問題!同時又保證username可以是中文的,而且重名也無所謂。

              附加:查看它的SQL配置文件,發現有selectUserByName這樣的方法,通過用戶名來查找用戶,起初怕是它在某些模塊中使用了。后來詳細查看,發現它只使用在后臺管理(即admin模塊)中的用戶管理。這個頁面提供了一個按用戶名來查找用戶的功能,所以也是非常合理的!


          剛進場的時候戲就落幕

          Feedback

          # re: JForum集成--用戶重名的一種解決方案  回復  更多評論   

          2009-10-21 21:50 by liuxin
          請問:
          JFORUM 1.2.8已經將SyntaxHighlighter納入支援 ,為什么我下載JFORUM.WAR ,測試就沒有出現類似JAVAEEYE這樣的
          程式碼語法高亮呢?
          我注意了一下:點擊javaeye的頁面源碼,可以看到頁面有類似<pre name="code" class="java"> 的代碼,
          我用JFORUM.WAR 測試的頁面沒有生成類似的代碼 ,倒是在HEADER.HTML 頁有這樣的定義: <#assign hasCodeBlock = hasCodeBlock?default(false)/>,在bottom.HTML <#if hasCodeBlock><#include "highlighter_js.htm"/>
          但是在JAVA 中只有net.jforum.view.forum.common.PostCommon private static void processText(Post post)
          boolean hasCodeBlock = false; ... if (hasCodeBlock) {JForumExecutionContext.getTemplateContext().put("hasCodeBlock", hasCodeBlock);}

          請問我在JAVA 代碼中怎么改動才能夠實現頁面程式碼語法高亮呢?
          期待你的幫助
          我的EMAIL:liuxinsudi@163.com

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 呈贡县| 荣成市| 扎赉特旗| 修武县| 龙南县| 玛沁县| 高尔夫| 盘山县| 梅河口市| 安庆市| 缙云县| 福州市| 岳阳市| 普宁市| 广饶县| 辽阳市| 宜川县| 收藏| 安丘市| 宝坻区| 梁河县| 义乌市| 腾冲县| 宁德市| 黄平县| 博爱县| 德江县| 东光县| 虹口区| 安仁县| 蓝田县| 图片| 苏尼特右旗| 洞头县| 澜沧| 禄劝| 竹北市| 个旧市| 剑川县| 曲阜市| 资溪县|