nighty

          折騰的年華
          posts - 37, comments - 143, trackbacks - 0, articles - 0
               JForum做為一個成熟的開源BBS論壇解決方案,提供了非常方便的SSO集成接口。它的主頁上和網(wǎng)上都有許多介紹如何用SSO方式進(jìn)行集成的辦法。這里不羅列,google可以找到許多資料,主要描述一下如何解決用戶名重名的一種方式。目前使用的JForum版本是2.1.8

               簡單地介紹一下采用的SSO方式。由于應(yīng)用上需要一個BBS,找了JForum做為一個子系統(tǒng),集成到現(xiàn)成的一個管理系統(tǒng)當(dāng)中,管理系統(tǒng)本身有一套完全的身份權(quán)限認(rèn)證方案,由于系統(tǒng)的安全要求不是特別嚴(yán)格,所以采了最直接和最省事的方式:Cookie寫入。即在管理系統(tǒng)登錄時,把用戶信息寫入Cookie,JForum從Cookie中讀取用戶信息進(jìn)行登錄。
               為JForum項目添加一個SSO接口的擴(kuò)展類CookieSSO,主要實現(xiàn)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中讀取在管理系統(tǒng)中放入的username。但是這里寫的是:ehrbbsuserid,主要是這個變量名來區(qū)分傳過來的內(nèi)容的不同。

              按照正常的方式就是從管理系統(tǒng)把一個用戶的username傳過來。然后在這里取出,return給調(diào)用方法進(jìn)行驗證。在實際項目中,問題就出在這里了
               舉例說有二個用戶名字都叫:李四,那么當(dāng)二個李四都同時登錄時,JForum的驗證方式就會出問題!它認(rèn)不清到底是哪個李四,數(shù)據(jù)庫查詢時只按第一個來!
               仔細(xì)看一下jforum的數(shù)據(jù)庫表設(shè)計,jforum_user這個表沒有display_user_name類似的字段,它就是把username做為顯示在頁面上的用戶名,如果不做集成,把它單獨做為一個BBS時,username既是登錄的用戶名,也是顯示在頁面上的用戶名。主要原因我想大概就是老外的思維方式跟中國人的不太一樣。中國人登錄的時候用英文,顯示的時候還有一個昵稱或是中文名等。
               所以把它集成的時候,用Cookie傳送一個username給JForum時就得用中文(而且重名的概率很大)。我們再跟進(jìn)一個它的代碼,看是誰調(diào)用了SSO接口的這個方法:
              結(jié)果發(fā)現(xiàn)是類: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去確定這個人是否存在?再繼續(xù)跟進(jìn)代碼就會發(fā)現(xiàn)最后調(diào)用了Dao的selectUserByName方法。

               解決的思路:修改JForum的數(shù)據(jù)庫表,并更改代碼和頁面文件是不科學(xué)的,工作量大,而且風(fēng)險比較高!那么就繼續(xù)把username用來保存中文名稱,它的user_id是一個自增的數(shù)字序列。在管理系統(tǒng)的用戶表中,擴(kuò)展一個字段bbs_user_id,用來保存在JForum中的用戶id,這個字段就肯定是唯一的,在管理系統(tǒng)登錄時,把這個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();
                          /* 重構(gòu)為按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);
                  }

              }

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

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


          剛進(jìn)場的時候戲就落幕

          Feedback

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

          2009-10-21 21:50 by liuxin
          請問:
          JFORUM 1.2.8已經(jīng)將SyntaxHighlighter納入支援 ,為什么我下載JFORUM.WAR ,測試就沒有出現(xiàn)類似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 代碼中怎么改動才能夠?qū)崿F(xiàn)頁面程式碼語法高亮呢?
          期待你的幫助
          我的EMAIL:liuxinsudi@163.com

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 奉新县| 巢湖市| 易门县| 固原市| 新竹市| 云浮市| 山西省| 砀山县| 如东县| 耿马| 潞西市| 仙游县| 和平县| 汽车| 武鸣县| 长兴县| 漳浦县| 铁岭县| 芦溪县| 会昌县| 托克托县| 宣化县| 临夏县| 壤塘县| 吉安县| 子长县| 博白县| 宁武县| 九龙坡区| 淮滨县| 财经| 吉安市| 平原县| 新巴尔虎右旗| 甘德县| 大厂| 彩票| 永定县| 锦州市| 盐山县| 闵行区|