MicroStrategy 对单点登录的支持。
[MicroStrategy Web 的设计模式]
MicroStrategy Web 应用的实现方式是使用类似Struts 的MVC 模式,整个应用的核
心是一个servlet 作为MVC 中的Controller 。所有的请求都发送给这个servlet,按照默
认的web.xml 中的定义,这个servlet 名称是 mstrWeb, mstrWeb 只接受两种参数evt=
或者页面参数 pg=
通过在客户自己的应用中,通过URL 就可以访问已经订制的报表、文档或者某个特定
页面(例如 共享报表页面)
[MicroStrategy Web 的URL 参数说明]
http://210.82.33.248/MicroStrategy/servlet/mstrWeb?evt=4001&src=mstrWeb.4001&reportViewM
ode=1&reportID=D08450DF4E71E2068B9AE
&Server=FBI&Uid=xxx&Pwd=xxx
在MicroStrategy Web 中要执行一个报表、或者访问一个已知的页面的时候,需要必
要的认证信息,从request 或者session 中需要提供的五个最基本认证参数如下:
Server ---- Intelligence Server 的HostName 或者IP 地址
Port –--- Interlligence Server 的监听端口,0 表示默认的端口
Project –--- 项目名称
Uid –--- MSTR 用户名
Pwd –--- MSTR 口令
在具体的应用集成中,往往要求业务用户在登陆业务系统后,在调用MicroStrategy 的时候,,
不需要再次输入用户信息,即单点认证。
在具体实现中,MicroStrategy Web 将上面的五个认证基本参数,封装在一个内部对象
中WebIServerSession。每个WebIServerSession 的实例代表一个用户的连接,其中
WebIServerSession 代表在Intelligence Server 中的一个用户会话,这个会话通过sessionID
进行唯一的标识。
[MicroStrategy Web 对SSO 的支持—ExternalSecurity]
MicroStrategy Web 提供ExternakSecurity 机制,来支持SSO。
External Security 提供如下的接口,这些接口实现以后的客户自定义的
ExternalSecurity 通过Web.xml 的配置加入到现有的Web 应用中,供MicroStratey Web
使用。在用户首次访问MicroStratey Web 的时候,或者是签退后重新访问的时候, Web
应用会调用实现中的handlesAuthenticationRequest 的方法,其返回值一共三种,根据返
回的参数的不同,Web 应用会调用ExternalSecurity 实现中的不同函数,参见下图。
图1
[通用的实现ExternalSecurity 步骤流程]
1、继承 AbstractExternalSecurity 父类,实现代码
public class WithSUN_ExternalSecurity extends AbstractExternalSecurity { ... ...
2、编译的类,打成jar 放在 web-inf/lib 下,或者按照包路径放在 web-inf/classes 下
3、修改 web.xml 中的 mstrWeb Servlet 配置中的 ExternalSecurityClass 参数,注释原
有的参数,使用用户定义的类,例如
<param-name>externalSecurityClass</param-name>
<!--param-value>com.microstrategy.web.app.DefaultExternalSecurity</param-value-->
<param-value>com.fbi.WithSUN_ExternalSecurity</param-value>
</init-param>
在不同的项目中,根据集成模式的不同,会有不同的集成模式。解决这个问题的核心是
如何根据传入的TOKEN 或者信息获取对应的MSTR 的登录信息。
下面就几种不同的模式进行介绍:
[模式一] Web Universal 作为单独的Web 应用使用
使用MicroStrategy 的登陆界面,(或者自定义的Login 页面)进行登陆。这个时候用户输
入的是外部用户的业务ID,以及Password。
[解决方式] 通过定义ExternalSecurity 类,实现用户输入的用户信息和MicroStrategy 之间
用户的转换。通常是基于数据库用户信息表,通过输入的信息映射到MSTR 的用户信息。
使用到了数据库表来存储用户名和密码。
[需要附加的包]
SQL Server 的 JDBC 包: jtds-0.9.jar
Oracle 的JDBC 包:
[模式二] 用户有自己的Web 应用,需要调用MicroStrategy Web 的应用
这种模式下不会提供MSTR 的任何登录的页面,但是要求从发起调用的Web 应用,在
访问MicroStrategy,需要通过Session 或者 Request 传递某个参数给MicroStrategy。
简化的实现是:在Web 应用调用handlesAuthenticationRequest 的时候返回常数
COLLECT_SESSION_NOW;
然后Web 应用会调用getWebIServerSession 方法,在getWebIServerSession 中系统
会传递两个参数,RequestKeys 和 ContainerServices,其中前者是对httpRequest 的封装,
后者则是对httpSession 的封装。需要在这个方法中返回一个WebIServerSession 的实例。
接下来,Web应用会调用底层的API 创建相应的Session,并将session 交于SessionManager
(内部对象)维护。
注意一个问题,传入的这个参数,可以考虑加密处理,可以将登录MSTR 的用户名和密码
信息加密后直接传入。另外更可为的方式为传入某一个临时的Key
利用 Key 从数据库,或者其他位置获得登陆MSTR 的用户名和密码。
[模式三] 与 SUN 的Identity Server 进行集成,SSO 软件进行集成,
客户化方式同模式二,特殊的是:
步骤1: 需要修改Web 的描述文件web.xml,将应用配置使用SUN SSO 认证,这样当未
认证的用户访问Web Universal 的时候,会进入SUN SSO 的登录界面。
样例,具体项目需要参考SUN 的文档
- <filter>
<filter-name>Agent1</filter-name>
<filter-class>com.sun.amagent.as.filter.AgentFilter</filter-class>
</filter>
- <filter>
<filter-name>Agent2</filter-name>
<filter-class>com.sun.amagent.as.filter.AgentFilter</filter-class>
</filter>
- <filter-mapping>
<filter-name>Agent1</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
- <filter-mapping>
<filter-name>Agent2</filter-name>
<url-pattern>/userinfo/*</url-pattern>
</filter-mapping>
步骤2:当用户输入统一的用户身份信息后,认证成功后,进入MicroStrategy 的界面,Web
Universal 会调用External Security 模块。
在handleAuthentication 或者 getWebIServerSession 中获得SUN Identity 的Token,调
用SUN SSO Client 的API,需要import SUN 的包:
import com.iplanet.sso.*;
import com.iplanet.am.sdk.*;
import com.sun.identity.authentication.*;
另外调用SUN 的API 获得认证成功后的令牌 Token,代码片断如下:
SSOTokenManager manager = SSOTokenManager.getInstance();
SSOToken ssoToken = manager.createSSOToken(reqKeys);
if(manager.isValidToken(ssoToken))
{
AMStoreConnection dpsc = new AMStoreConnection(ssoToken);
AMUser dpUser = dpsc.getUser(ssoToken.getPrincipal().getName());
uid = dpUser.getStringAttribute("uid");
cn = dpUser.getStringAttribute("cn");
employeeNo = dpUser.getStringAttribute("employeenumber");
alias = dpUser.getStringAttribute("iplanet-am-user-alias-list");
mail = dpUser.getStringAttribute("mail");
entrydn = dpUser.getStringAttribute("entrydn");
}
通过认证源的返回的信息,如果正常,那么需要根据其他的信息获得MSTR 的登录信息。
否则,需要参见下面 [关于认证失败的处理]
[模式四] 与第三方开发的认证进行集成的样例:
样例1: 用户自己开发了portal,实现集中的认证源,那么需要在External Sercurity 类的
handelAuthentication 或者getWebIServerSession 中利用下面的代码:
URL url=new URL("http://portal.xbxs.petrochina:38081/ssoauth/SSOValidate?tokenID=" + tokenId);
URLConnection con=url.openConnection();
con.setUseCaches(false);
java.io.BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line= br.readLine();
while(null != line){
if (line.indexOf("SUCCESS")>-1) break;
通过认证源的返回的信息,如果正常,那么需要根据其他的信息获得MSTR 的登录信息。
否则,需要参见下面 [关于认证失败的处理]。
[关于认证失败的处理]
第一种方法是:
在 getwebiserversession 中,用提供的credential 创建session,如果创建session 不成功,
getwebiserversession 会自动return null。这时getfailureurl 方法会被call with reason =1。
可以在getfailureurl 方法中指定reason=1 时出现的错误信息页面的url
第二个方法是:
1. 在handlehandlesAuthenticationRequest 中用非建立session 的方法验证credential
2. 如果验证ok,就call getWebIServerSession,create mstr session
3. 如果验证不ok,就call getCustomLoginURL, 然后在getCustomLoginURL 方法中,
指定error page 的url
这两个方法那个更好,取决于如何验证mstr credential。如果credential 只能通过session
是不是null 来验证,就用方法1。如果是通过其他方法验证credential,就用方法2。