如题。

解决方案 »

  1.   

    SSO:单点登录.一般是系统之间整合需要解决的一个问题.例如你之前做了个BBS或者一个CMS的系统.你在完成一个全新系统时候需要用到BBS这个系统的话..你就可能面临一个整合的问题.(除非你自己决定从新做个BBS上去) 对于我们已有的WEB应用中的用户,若该用户已经登陆,并通过 联结迁移到BBS页面时,BBS要能够识别该用户已经登陆(不需要二次登陆)才不会让用户感到别扭(对用户来说,就好像使用的是同一个系统似的)。 下面看下Jforum对于SSO的处理. 
    首先找到SSO处理所有类:net.jforum.sso下的SSO(需要实现的接口) SSOUtils(工具类)类;net.jforum.ControllerUtils;net.jforum.JForum 
    首先从xml中可以看到net.jforum.JForum这是整个系统一个核心的servlet.所以所有访问将通过该实体类 
    1.当一个用户访问JForum时.刷新session
    ControllerUtils utils = new ControllerUtils();   
    // 刷新session   
    utils.refreshSession();  
      

  2.   

    2.进入ControllerUtils的refreshSession() 
    public void refreshSession()   
        {   
            UserSession userSession = SessionFacade.getUserSession();//获取系统用户session   
            RequestContext request = JForumExecutionContext.getRequest();//获取封装后的request值   
      
            if (userSession == null) {//如果userSession不存在话   
                userSession = new UserSession();   
                userSession.registerBasicInfo();//初始化基础信息   
                userSession.setSessionId(request.getSessionContext().getId());   
                userSession.setIp(request.getRemoteAddr());   
                SessionFacade.makeUnlogged();//清除登录session的值   
      
                if (!JForumExecutionContext.getForumContext().isBot()) {//如果不是机器登录   
                    // Non-SSO authentications can use auto login   
                    /**  
                     * 要启用sso功能话需要配置SystemGlobals.properties的中  
                     * authentication.type的值=ConfigKeys.TYPE_SSO  
                     */  
                    if (!ConfigKeys.TYPE_SSO.equals(SystemGlobals.getValue(ConfigKeys.AUTHENTICATION_TYPE))) {   
                        if (SystemGlobals.getBoolValue(ConfigKeys.AUTO_LOGIN_ENABLED)) {   
                            this.checkAutoLogin(userSession);   
                        }   
                        else {   
                            userSession.makeAnonymous();   
                        }   
                    }   
                    else {   
                        this.checkSSO(userSession);//检测sso   
                    }   
                }   
      
                SessionFacade.add(userSession);//将userSession设置到SessionFacade   
            }   
            else if (ConfigKeys.TYPE_SSO.equals(SystemGlobals.getValue(ConfigKeys.AUTHENTICATION_TYPE))) {//是否启用sso   
                SSO sso;   
                   
                try {   
                    /**  
                     * ConfigKeys.SSO_IMPLEMENTATION   
                     * 取决你用什么方式实现SSO 可以是Cookies形式或者JDAP等形式而相应完成的实现类需要在SystemGlobals.properties配置 sso.implementation = 实现类完整路径  
                     */  
                    sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();   
                }   
                catch (Exception e) {   
                    throw new ForumException(e);   
                }   
      
                // If SSO, then check if the session is valid   
                if (!sso.isSessionValid(userSession, request)) {//session值是否通过SSO验证.   
                    SessionFacade.remove(userSession.getSessionId());   
                    refreshSession();   
                }   
            }   
            else {   
                SessionFacade.getUserSession().updateSessionTime();   
            }   
        }  
      

  3.   

    从代码中可以看出.checkSSO这个方法将是重点: 
    protected void checkSSO(UserSession userSession)   
        {   
            try {   
                /**  
                 * ConfigKeys.SSO_IMPLEMENTATION   
                 * 中对应SystemGlobals.properties配置中SSO的实现类  
                 * 取决你用什么方式实现SSO   
                 * 可以是Cookies形式或者JDAP等形式 sso.implementation = 实现类完整路径  
                 */  
                SSO sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();   
                /**  
                 * sso检测用户.返回为用户的值  
                 */  
                String username = sso.authenticateUser(JForumExecutionContext.getRequest());   
                /**  
                 * 若返回了一个null,则设置为“Anonymous” (设置匿名用户)  
                 * checkAutoLogin()将调用makeAnonymous()里面设置的匿名cookies值  
                 * 若一个“Anonymous”用户试图访问权限以外的页面,  
                 * JForum将根据SSO的设置导航到登陆页面,  
                 * 同时传递给一个登陆成功后应该迁移到的地址参数给login页面。  
                 */  
                if (username == null || username.trim().equals("")) {   
                    userSession.makeAnonymous();   
                }   
                /**  
                 *  若返回了一个不为空的username时,  
                 * JForum将会检查是否匹配JForum数据库的userid。  
                 *  若没有匹配的userid,JForum将动态加以创建  
                 *   
                 */  
                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);//JForum设置该user为登陆状态    
                    }   
      
                    this.configureUserSession(userSession, utils.getUser());   
                }   
            }   
            catch (Exception e) {   
                e.printStackTrace();   
                throw new ForumException("Error while executing SSO actions: " + e);   
            }   
        }