三、Weblogic Portal的用户
提到SSO,就不能不说说Weblogic Portal的用户信息。作为一个统一,简单,可扩展的企业级应用平台Weblogic Platform中的一部分,Weblogic Portal被容纳在Weblogic Platform统一的安全框架中,它使用的用户和组,就是weblogic Server的用户和组,但是与Weblogic Server不同的是,它的角色是Portal特有的,与Server是完全不同意义的,需要注意不要混淆了。
Weblogic Server安装后缺省时是使用自带的内嵌的LDAP来进行用户,组和角色的管理的,在身份验证提供者中,有一个DefaultAuthenticator,就是对这部分用户,组和角色来进行管理的提供者。
Weblogic Portal8.1.3可以支持多个用户身份验证提供者,配置是在Server的控制台中进行,在Weblogic Portal的管理工具中,在管理用户和组的时候,可以在多个安全提供者之间切换,进行管理。
在Weblogic Server控制台中,点击Security > Realms > myrealm> Authentication Providers,可以看到DefaultAuthenticator,同时,还能看到可以新建很多种类的身份验证提供者,包括:
Configure a new Default Identity Asserter...
Configure a new MedRec Sample Authenticator...
Configure a new Open LDAPAuthenticator...
Configure a new Novell Authenticator...
Configure a new iPlanet Authenticator...
Configure a new RDBMSAuthenticator...
Configure a new Default Authenticator...
Configure a new Realm Adapter Authenticator...
Configure a new WSRPIdentity Asserter...
Configure a new LDAPX509Identity Asserter...
Configure a new Active Directory Authenticator...
可以看到,Weblogic Server可以配置使用多种主流的LDAP服务器来存储用户和组,同时,也支持数据库和AD。通过设置,可以指定使用哪个身份验证提供者作为缺省的。也可以设置多个Provider直接的验证关系如何。
本文中不会对如何配置进行说明,感兴趣的朋友,可以查阅Weblogic Server关于Security的相关的帮助。使用数据库作为验证,可以参见笔者另外一个帖子:
http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=101&threadID=18563由此可以看到,如果客户需要的SSO指的就仅仅是,能够使用他们企业内部已有的LDAP或者AD用户,进行Weblogic Portal登录和身份验证的话,那么,只要配置多个身份验证提供者就可以了,就可以使用那些已经存在的用户。但是,如果客户需要的SSO并不局限于此,还需要在Portal上登录以后,再访问其他一些基于Web的应用系统时,就不需要重复输入用户名和密码和重复登录了,那么,仅仅通过配置是无法实现的。即便那些系统和Portal理想状态下都使用相同的LDAP或者AD用户,由于每个系统验证用户是否登录以后的机制不同,还是需要进行定制开发的。四、自己开发实现SSO
Portal作为统一的入口,将其他基于Web的应用集成到Portal中,方式可以是多种多样的,最简单的是Portal上提供链接,直接打开其他系统的界面,进行操作;再复杂一点的就是通过Frame或者Iframe的方法,将其他系统的界面嵌入到Portal中,但实质还是使用其他系统的界面,Portal只是从大范围(例如包含了其他应用的Portlet)来控制用户的访问权限,这两种主要解决的就是能够绕过其他系统的登录,然后让其他系统能够识别当前用户的对应身份,至于其他系统内部自己的个性化,权限等,还是由各个系统自己控制的。Weblogic Portal的Web应用集成还有其他方式,例如通过web clipping的方式,生成Portlet;或者通过HttpControl,取得Http回应的内容,组成Portlet;或者完全使用后端系统的API,重构Web内容,例如通过Lotus Domino的API,访问Lotus Domino的数据库,直接读取视图或者文档的信息等。但这几种方式都已经不再使用原来的系统界面,所以,涉及的内容在本文SSO讨论中没有包括。本节讨论的就是开始时提到的两种方式如何解决。
经过前面身份验证,Session,Cookie等方面的说明,我想,很多人大概已经知道如何自己编写程序来实现简单的SSO了,在论坛上笔者也看到有的朋友这样做了,其实说来很简单:
1、在数据库或者LDAP中存储Portal用户和其他系统用户的对应关系,包括其他系统用户名称和密码,根据不同系统的验证特点,有的可能还要存储密码的密文形式。
2、在Portal登录时,或者在切换到其他系统时,通过Iframe将用户名称和密码通过URL传递过去,进行后端的登录。
以后端系统为Dev2dev.bea.com.cn为例,可以通过查看登录页面的源文件,知道Form的action是login.jspa,那么,当Portal用户验证正确以后,可以在页面中加入
<iframe width=1 height=1 src='http://dev2dev.bea.com.cn/bbs/login.jspa?username=YOURUSERNAME&password=YOURPASSWORD'></iframe>
<a href="http://dev2dev.bea.com.cn/bbs/settings!default.jspa">Dev2dev.bea.com.cn</a>
将上面的YOURUSERNAME和YOURPASSWORD替换为Portal用户对应的用户名称和密码,打开页面后,点击该链接,可以看到,当前用户已经是登录以后的身份。
当然,可以去掉下面的连接,直接设置iframe的width和height为足够大,就可以将dev2dev.bea.com包括在其中。
以上应该是一个JSP页面(因为你要动态的设置名称和密码),通过该JSP页面产生Portlet,就可以嵌入到Portal中,正如我们前面所说,你不能通过Portal控制你登录以后的样式,个性化等属性,但是你可以通过控制用户访问该Portlet的权限,从而实现Portal内高层次的个性化和显示控制。(其实,通过JavaScript,也完全可以改变Iframe中的内容和样式,这个超出本文的主题,略过)
以上就是一个SSO的自己编程的简单实现,但是,这种方法具有很多需要注意的地方和局限性:
1、对方的登录表单,可能不仅仅是传递了用户名称和密码,可能还有其他的参数,需要多次尝试,如果能够看到对方验证的代码最好。
2、对方有可能进行了Form是POST还是GET提交的判断(例如,验证页面是Servlet),如果一定需要使POST,那么可以使iframe中src是一个相同的form表单,action指向对方的验证页面,然后,通过Javascript,进行隐式提交;更有甚者,有的验证页面还判断了是否是本服务器提交的请求,那么,就要嵌入对方的登录表单,然后在iframe所在的页面内,通过Javascript使iframe内的页面提交,完成登录。
3、有的系统为了安全,密码传输前已经在客户端通过Javascript进行了加密,注意检查。
4、有的系统很特别,一定要在浏览器的_top窗口中进行验证,或者验证以后在_top中打开后继的页面,对于这种系统,请修改对方的程序,否则很难解决。笔者曾经就遇见过此类案例,尝试多次无果,幸好后来发现对方系统能够设置后继的页面,将后继的页面设置为Portal,再转回Portal才可以。
5、Portal用户会和多个系统的用户有对应关系,需要设计一个好的数据结构,如果后端系统为多个,不一定非要在Portal登录验证后隐式登录所有的系统,可以在需要显示哪个系统时,再隐式登录。五、小结
以上就是个人关于SSO和Weblogic Portal的实现的一些看法,经验和心得体会,希望能对相关朋友有所帮助。值得一提的是,Weblogic Portal通过Portlet源的多样性和灵活性,为自己开发编程实现SSO,提供了强有力的支持。

解决方案 »

  1.   

    Weblogic Portal8.1中实现分页显示
    我们现在至少有三种以上的方案可以解决:
    1、在JSP页面上用netui:anchor 来实现页面到action的跳转,在action中进行处理之后,在回到本页面。
    2、如果将代码写到JSP中,我们可以通过取得当前的page的com.bea.portlet.PostbackURL 来进行定位。
    3、参考workshop中由Control自动创建的JPF中的实现方式。第一种方案思路如下:
    页面流开始,在Action中取出所有要显示的数据,分页,并显示第一页。当在jsp中点击第二页时,页面流回到Action,在Action中首先得到页数,然后计算第二页应该load的数据,并load这些数据,然后跳向原先的jsp,但是在这个jsp中绑定的数据已经是第二页的数据了。
    代码详见:testpageflow第二种方案思路:
    <%
        PostbackURL url = PostbackURL.createPostbackURL(request, response);
        int i = 1;
        while(i<10)
        {
            url.removeParameter("page");
            url.addParameter("page",new Integer(i).toString());
        %>
        <a href=<%=url%>>第<%=i%>页</a>
        <%
            i++;
        }
    %>
    当jsp,自己调用自己的时候,url地址不要写文件名,而是利用portlet的类,根据当前环境(request & response)先创建一个url,然后跳转到这个url,置于不同页需要不同的参数(page)值,则在代码中使用url. addParameter方法,注意在add之前最好先清一下Parameter,否则可能加得很长。
    代码详见:pageTest.jspJava page flow 是基于strus的,建议将逻辑代码都写到action中,使用workshop提供的NetUI,一般的功能都可以实现。在jsp中尽量不写代码,尽量不要jsp之间直接跳转。以上两个例子您可以直接拖入您的工程,可以直接运行。形成portlet放入portal后也测试过了。
    第三种方案思路:参考workshop中由Control自动创建的JPF中的实现方式。
    附件:
    http://dev2dev.bea.com.cn/bbs/servlet/D2DServlet/download/101-12443-65787-523/说明及实例.rar第三方插件集成
    1、Weblogic 8.1 Portal和Domino的集成问题
    Q: 我用Compoze Portlets来进行Portal和Domino的集成,按照说明配置好,并测试与Domino联接是通了,但还是不能读到Domino中的数据,搞了好久也不知其中道理。哪位大哥能说说有关于这方面的内容? A:我配过两次都很顺利,没有什么问题,从错误信息上看不出什么东东,在配置compoze之前需要确定以下一些前提条件:
    1、安装BEA Weblogic Platform8.1或BEA Weblogic portal8.1
    2、删除以前安装的其他版本的Compoze Domino Service
    3、需要Windows2000 SP3或更高的版本(如果是在windows上的话)
    4、需要Lotus Domino R5.08(或更高)或Domino R6,并启动了HTTP任务
    5、需要安装Lotus Administrator client
    认真看一个compoze的文档吧,如果还有问题可以给[email protected]发邮件,老外效率蛮高的。dev2dev学堂文档:《Compoze安装说明 实现用WebLogic Portal 与Domino服务互联》 
    http://dev2dev.bea.com.cn/bbs/school/guide/wlportal/20031165.html 
    2、BEA所推荐使用的Kapow产品是否支持中文环境?
    Kapow RoboSuite是专门用于Web应用集成的一组套件,它可以实现数据收集、页面剪辑和部分功能集成。其产品有专门的weblogic版本,它可以在weblogic server、weblogic portal、weblogic Integration中使用,支持7.0和8,1两个版本对中文环境的支持没有问题,如果显示中文乱码,请设置CONTENT ENCODING现在没有中文的资料,比较简单,可以按照RoboSuite Quick Start Guide.pdf 来学习Kapow RoboSuite, BEA WebLogic EditionKapow RoboSuite 5.0 文档:
    http://kdc.kapowtech.com/html/index.php?module=PostWrap&page=documentation5&POSTNUKESID=386810a25b464879c7ecc81c90fab 
    性能
    1、请教portal for aix的运行问题 
    Q: 我做了个portal系统,但是运行半个小时左右就不正常了,那位在weblogic portal 8。1 for aix上开发过系统,是否有成功的案例,否则我就怀疑系统本身不稳定了 A: 这个问题一般是由于AIX操作系统本身的系统参数配置造成的,我本人建议从一下几方面进行考虑:
    1)AIX操作系统的版本;
    2)AIX操作系统是否打要求PATCH;
    3)AIX的系统参数是否经过调整;
    4)查询BEA关于运行在AIX方面的文档; 
    在没有调整操作系统参数的时候会出现效率低下的问题,调优之后,效率很不错的。我们PORTAL也是运行在AIX上的,起初效率也很慢,怀疑是PORTAL在AIX上运行效率低下,对PORTAL经过各方面的调优,也包括BEA PS,起色不大;之后,将调优的重点转移到服务器上,经过调优后,效率还是不错的,就是调优操作系统化费了一段事件,需要调的参数太多了。 可能是JDK的问题,wlp8.1GA版要求的JDK版本是:IBM SDK 1.4.1 32-bit PTF: ca141-20030703a 对portal for aix需要IBM的JDK,最好还是2003.11月以后的版本
      

  2.   

    安全
    1、关于weblogic administration portal使用的方法
    Q: 目前我们的项目需要使用weblogic8进行portlet的开发,现在遇到了一个技术上的难题,就是客户需要我们使用weblogic8自带的weblogic administration portal管理工具,进行用户和组的管理,并且要求用户和用户之间有权限的关系。还请大家帮帮忙,谢谢了A: weblogic 8.1 portal中,用户和组不再直接具有权限,而是将角色(role)作为属性赋予用户和组,角色的概念是动态的权限,可以看作一系列权限的组合。管理界面中的角色有:管理角色和访问角色两种。
    2、在portal中使用数据库保存用户信息
    最近写了一个东西,不知道发在哪里,就放到portal这里吧,其实bea也有其他的方案,比如自己作验证的部分的例子,不过一般是由bea 的 PS 出面做,就不讨论了。
    在本例中我使用的是weblogic portal8.1和oracle817。在weblogic platform也可以采用这种方式配置。
    首先创建一个portal的domain。我的路径是:D:\bea\user_projects\domains\portalDomain。启动potalDomain。进入控制台:http://localhost:7001/console1.创建表
    在路径:D:\bea\weblogic81\portal\db\oracle\817 下找到文件:p13n_create_tables.sql,在oralce的SQL/PLUS下执行该文件的语句,创建相应的表,oracle这边的配置结束。
    在weblogic的控制台中进入:Security->Realms->myrealm->Providers->Authentication。在右面找到:Configure a new RDBMSAuthenticator...点击进入配置页面:点击创建按钮,点击detail页,进入,配置信息如下:
    <com.bea.p13n.security.providers.authentication.RDBMSAuthenticator
                ControlFlag="OPTIONAL"
                DatabaseDriver="oracle.jdbc.driver.OracleDriver"
                DatabasePassword="manager"
                DatabaseURL="jdbc:oracle:thin:@localhost:1521:jwl"
                DatabaseUsername="system" Debug="false"
                Name="Security:Name=myrealmRDBMSAuthenticator"
                Realm="Security:Name=myrealm" SchemaProperties="user=system;password=manager;serverName=localhost;SID=jwl;portNumber=1521"/>
    注意:ControlFlag="OPTIONAL"。
    创建用户和组,注意在选择的时候要选择RDBMSAuthenticator。其中,Administrators组是一定要建的,而且用户要是这个组里面的,而后即可使用该用户登陆系统了。
    在oracle数据库中可以看到你创建的用户信息,主要是user_***和group_***几张表。3、如何使用数据库作为WLS&WLP的用户验证
    作为一个统一,简单,可扩展的企业级应用平台Weblogic Platform中的一部分,Weblogic Portal被容纳在Weblogic Platform统一的安全框架中,它使用的用户和组,就是weblogic Server的用户和组,但是与Weblogic Server不同的是,它的角色是Portal特有的,与Server是完全不同意义的,需要注意不要混淆了。
    Weblogic Server安装后缺省时是使用自带的内嵌的LDAP来进行用户,组和角色的管理的,在身份验证提供者中,有一个DefaultAuthenticator,就是对这部分用户,组和角色来进行管理的提供者。Weblogic Portal8.13可以支持多个用户身份验证提供者,配置是在Server的控制台中进行,在Weblogic Portal的管理工具中,在管理用户和组的时候,可以在多个安全提供者之间切换,进行管理。
    在Weblogic Server控制台中,点击Security > Realms > myrealm> Authentication Providers,可以看到DefaultAuthenticator,同时,还能看到可以新建很多种类的身份验证提供者,包括:
    Configure a new Default Identity Asserter...
    Configure a new MedRec Sample Authenticator...
    Configure a new Open LDAPAuthenticator...
    Configure a new Novell Authenticator...
    Configure a new iPlanet Authenticator...
    Configure a new RDBMSAuthenticator...
    Configure a new Default Authenticator...
    Configure a new Realm Adapter Authenticator...
    Configure a new WSRPIdentity Asserter...
    Configure a new LDAPX509Identity Asserter...
    Configure a new Active Directory Authenticator...
    可以看到,Weblogic Server可以配置使用多种主流的LDAP服务器来存储用户和组,同时,也支持数据库和AD。
    点击Configure a new RDBMSAuthenticator...,输入Provider的名字,选择Control Flag, Control Flog的意义见下文。点击Apply。
    关于Control Flag的说明如下:
    REQUIRED—The Authentication provider is always called, and the user must always pass its authentication test. 
    REQUISITE—If the user passes the authentication test of this Authentication provider, other providers are executed but can fail (except for Authentication providers with the JAAS Control Flag set to REQUIRED). 
    SUFFICIENT—If the user passes the authentication test of the Authentication provider, no other Authentication providers are executed (except for Authentication providers with the JAAS Control Flag set to REQUIRED) because the user was sufficiently authenticated. 
    OPTIONAL—TThe user is allowed to pass or fail the authentication test of this Authentication provider. However, if all Authentication providers configured in a security realm have the JAAS Control Flag set to OPTIONAL, the user must pass the authentication test of one of the configured providers. 
    Details标签里面配置数据库的信息,与配置数据库连接池一样,就是用户名,密码什么的,具体不再描述。
    如果你使用了WLP带的Pointbase,那么其中用户表和group表分别为user_security和group_security,我尝试了一下,在user_security中添加一条记录,那么在控制台中是可以看到用户的。但是要注意的是,password是密文,我建议是你先在控制台创建一个用户,   设置密码后,在数据库中能够看到密码的加密格式,然后在数据库添加其他用户时,使用该密文,至少可以保证你的用户密码是知道的。
    如果,密码要不同,可以尝试使用如下代码加密密码:
    import java.security.MessageDigest;
    import weblogic.utils.encoders.BASE64Encoder;
    ......
    private String encodePassword(String password)
    {
      MessageDigest messageDigest=MessageDigest.getInstance("MD5");
      BASE64Encoder encoder=new BASE64Encoder(); 
      return encoder.encodeBuffer(messageDigest.digest(password.getBytes()));
    }
    (以上代码试验过,正确)使用数据库认证,需要创建一些组的,你最好在数据库表中,按照Weblogic缺省带有的那些组,建立一些组,因为,WLS的Role有些是根据组配置的,特别是WLS的管理员。
    当然你也可以保留原有的WLS基于LDAP的认证,应用的用户再使用RDBMS,就是两个验证提供者并存,但是要注意的是,需要设置你添加的验证提供者和DefaultAuthenticator的Control Flag为SUFFICIENT或者REQUISITE。(我试验时都设置的SUFFICIENT)
    以上注意的是,我是在Portal Domain中,数据库使用point base试验成功的,数据库中缺省已经带有了表,在Weblogic Server Domain中尝试失败,由于时间关系,没有查找原因。
    缺省时RDBMS认证需要的表文件和相关文件,可以见BEA_HOME\weblogic81\portal\db\下各种数据库目录下p13n_xxx_xxx.sql。
    http://e-docs.bea.com/wls/docs81/ConsoleHelp/security_7x.html#1175366
    http://e-docs.bea.com/wls/docs81/ConsoleHelp/domain_rdbmsrealm_config_database.html4、WebLogic用户及权限管理API
    1、Weblogic MBean
    要存取WLI8/WLP8中的组和用户信息是通过WLS8提供的操作组和用户的API实现的。在WLS8中的安全(组、用户等信息)是用JAAS方式来实现的,这些安全信息存储在WLS内嵌的LDAP Server(客户可以通过配置将安全信息存储在其它的LDAP服务器,如:IDS、NDS等)中。WLS对缺省安全配置下的用户和组信息的访问是通过AuthenticationProvider提供的API实现的。缺省的WLS AuthenticationProvider实现了AuthenticationProviderMBean接口,此接口提供了作为管理AuthenticationProvider所需的所有方法定义,它对应的接口类是:weblogic.management.security.authentication.AuthenticationProviderMBean。通过在WLS中访问MBean的方法可以获取继承此MBean的针对具体安全实施的MBean。缺省的WLS使用weblogic.security.providers.authentication.DefaultAuthenticatorMBean对应缺省的安全实施。通过调用此安全实施MBean相应的方法即可操作存储在安全中的组和用户信息。  以下是取得DefaultAuthenticatorMBean实现的例程:
    InitialContext ctx = new InitialContext();
    MBeanHome home = null;
    try
    {
        home = (MBeanHome)ctx.lookup(MBeanHome.LOCAL_JNDI_NAME);
        AuthenticationProviderMBean[] providers = home.getActiveDomain().getSecurityConfiguration().findDefaultRealm().getAuthenticationProviders();
        for(int i=0;providers!=null&&i<providers.length;i++)
        {
            if((providers[i].wls_getInterfaceClassName()).equals(
                "weblogic.security.providers.authentication.DefaultAuthenticatorMBean"))
            {
                DefaultAuthenticatorMBean damb = (DefaultAuthenticatorMBean)providers[i];
                // 将取得的MBean保存到自己实现的Java Bean中并保存到HTTP Session中以供其它JSP使用
                mbeanRef.setDefaultAuthenticatorMBean(damb);
                break;
            }
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
      

  3.   

    2、操作组和用户的API&#61656; 列出组内的所有成员(子组和用户):
    函数名: listGroupMembers
    参数:
    名称 类型 描述
    GroupName String 父组的名称
    memberNameWildcard String 成员选取查询串,“*”表示所有匹配
    maximumToReturn int 最大返回数
    返回值:
    类型 描述
    String 返回成员(子组和用户)结果集对应的游标(cursor)。
    通过weblogic.management.utils.NameListerMBean的方法处理结果集&#61656; 创建组:
    函数名: createGroup
    参数:
    名称 类型 描述
    GroupName String 组的名称
    GroupDescription String 组的描述
    返回值: void
     
    &#61656; 指定组的成员(用户或子组)关系:
    函数名: addMemberToGroup
    参数:
    名称 类型 描述
    ParentGroupName String 父组的名称
    userOrGroupName String 要指定的成员(用户或子组)的名称
    返回值: void
     
    &#61656; 去除成员(用户或子组)关系:
    函数名: removeMemberFromGroup
    参数:
    名称 类型 描述
    ParentGroupName String 父组的名称
    userOrGroupName String 要去除的成员(用户或子组)的名称
    返回值: void&#61656; 删除组:
    函数名: removeGroup
    参数:
    名称 类型 描述
    GroupName String 组的名称
    返回值: void&#61656; 判断组是否存在:
    函数名: groupExists
    参数:
    名称 类型 描述
    GroupName String 组的名称
    返回值:
    类型 描述
    boolean 组是否存在(true表示存在,false表示不存在)&#61656; 创建用户:
    函数名: createUser
    参数:
    名称 类型 描述
    Username String 用户名
    Password String 密码
    UserDescription String 用户描述
    返回值: void&#61656; 删除用户:
    函数名: removeUser
    参数:
    名称 类型 描述
    Username String 用户的名称
    返回值: void&#61656; 判断用户是否存在:
    函数名: userExists
    参数:
    名称 类型 描述
    Username String 用户的名称
    返回值:
    类型 描述
    boolean 用户是否存在(true表示存在,false表示不存在)

    &#61656; 查询组:
    函数名: listGroups
    参数:
    名称 类型 描述
    groupNameWildcard String 组的选取查询串,“*”表示所有匹配
    maximumToReturn int 最大返回数
    返回值:
    类型 描述
    String 返回组结果集对应的游标(cursor)。
    通过weblogic.management.utils.NameListerMBean的方法处理结果集&#61656; 查询用户:
    函数名: listUsers
    参数:
    名称 类型 描述
    UserNameWildcard String 用户的选取查询串,“*”表示所有匹配
    MaximumToReturn int 最大返回数
    返回值:
    类型 描述
    String 返回用户结果集对应的游标(cursor)。
    通过weblogic.management.utils.NameListerMBean的方法处理结果集&#61656; 查询所有的父组:
    函数名: listMemberGroups
    参数:
    名称 类型 描述
    groupName String 组的名称
    返回值:
    类型 描述
    String 返回父组结果集对应的游标(cursor)。
    通过weblogic.management.utils.NameListerMBean的方法处理结果集