/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.core.web.rmi;
import java.io.IOException;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
import com.jinhe.tss.core.exception.BusinessServletException;
import com.jinhe.tss.core.sso.Environment;
import com.jinhe.tss.core.sso.IOperator;
import com.jinhe.tss.core.sso.IPWDOperator;
import com.jinhe.tss.core.sso.IdentityTranslator;
import com.jinhe.tss.core.sso.IdentityTranslatorFactory;
import com.jinhe.tss.core.sso.appserver.AppServer;
import com.jinhe.tss.core.sso.context.Context;
/**
* <p> DominoLoginHelper.java </p>
*
* 和Domino类系统进行单点登录时的一些工具方法
*/
public class DominoLogin {
private DominoLogin(){}
private static DominoLogin instance;
public static DominoLogin instance(){
if(instance == null)
instance = new DominoLogin();
return instance;
}
private static final Logger log = Logger.getLogger(DominoLogin.class);
/**
* <p>
* 验证用户是否登录Domino服务器,如果未登录则登陆系统;如果登录时密码为手工输入,则重新保存新密码。
* 登录模拟如下的地址:
* http://www.gzcz.com:8081/names.nsf?Login&Username=admin&Password=shulicq&RedirectTo=/app/testxml.nsf/success.xml
* 如果用户名密码正确则直接转向到/app/testxml.nsf/success.xml判断是否登录成功,成功则将cookie信息返回到Response中。
*
* </p>
* @param appServer
*/
public void loginDominoServer(AppServer appServer) throws IOException, BusinessServletException {
if (!validateIdentity4Domino(appServer)) {
// 用户未登录,则登录待转向的应用
log.debug("LoginDomino:开始登陆 Domino Server (appCode:" + appServer.getCode() + ") ......");
IOperator operator = getRelevantOperator(appServer);
// 创建HttpClient对象
HttpClient client = HttpClientHelper.instance().getHttpClient(appServer);
PostMethod login = new PostMethod(appServer.getBaseURL() + appServer.getLoginAction()){
// 复写PostMethod.getRequestCharSet()的编码设置为 UTF-8,以支持中文参数,如loginName为中文名
public String getRequestCharSet() {
//return super.getRequestCharSet(); // 默认为ISO-8859-1
return "UTF-8";
}
};
String loginName = operator.getLoginName();
if (loginName == null)
throw new BusinessServletException("对应用户没有登录名,请编辑系统(" + appServer.getCode() + ")的对应用户");
login.addParameter("Username", loginName);
String password = Context.getRequestContext().getPWD();
boolean needSavePassword = true;
if (password == null && operator instanceof IPWDOperator) {
IPWDOperator passwordOperator = (IPWDOperator) operator;
password = passwordOperator.getPassword();
needSavePassword = false; //if判断password不是前台传进来而是operator本来就有的,不需要再次保存
}
password = (password == null ? "" : password);
login.addParameter("Password", password);
login.addParameter("RedirectTo", appServer.getOnlineAction());
try {
int statusCode = client.executeMethod(login);
log.debug("LoginDomino:Login(" + statusCode + ")");
if (statusCode == HttpStatus.SC_OK) {
dealWithLoginResponse4Domino(loginName, appServer, login);
} else if ((statusCode == HttpStatus.SC_MOVED_TEMPORARILY)
|| (statusCode == HttpStatus.SC_MOVED_PERMANENTLY)
|| (statusCode == HttpStatus.SC_SEE_OTHER)
|| (statusCode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
dealWithRedirect4LoginDomino(loginName, appServer, client, login);
} else {
throw new BusinessServletException(appServer.getName()
+ "(" + appServer.getCode() + ")连接错误,错误代码:" + statusCode);
}
setReturnCookie2Reqeust4Domino(appServer, client);
if (needSavePassword) {
log.debug("LoginDomino:Save Password(" + password + ")");
IdentityTranslatorFactory.getTranslator().savePassword(operator.getId(), password);
}
} finally {
login.releaseConnection();
}
log.debug("LoginDomino:登陆完成 Domino Server");
}
}
/**
* <p>
* 获取应用系统的用户信息
* </p>
* @param appServer
* @return
*/
private IOperator getRelevantOperator(AppServer appServer) {
IdentityTranslator translator = IdentityTranslatorFactory.getTranslator();
return translator.translate(Environment.getOperatorId(), appServer.getCode());
}
/**
* <p>
* 设置登录Domino成功后SessionId到数据请求对象中
* </p>
* @param appServer
* @param client
*/
private void setReturnCookie2Reqeust4Domino(AppServer appServer, HttpClient client) {
// 转发返回Cookies
Cookie[] cookies = client.getState().getCookies();
for (int i = 0; i < cookies.length; i++) {
String cookieName = cookies[i].getName();
log.debug("LoginDomino:Cookie(" + cookieName + ")");
if (cookieName.equals(appServer.getSessionIdName())) {
String cookieValue = cookies[i].getValue();
log.debug("LoginDomino: 成功取到登陆domino需要的cookie :" + cookieName + " (" + cookieValue + ")");
cookieName = appServer.getCode(); //修改cookie的名称为OA code
javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(cookieName, cookieValue);
cookie.setPath(Context.getApplicationContext().getCurrentAppServer().getPath());
Context.getRequestContext().getRequest().addCookie(cookie);
}
}
}
/**
* <p>
* 处理登录Domino服务器请求时Redirect的情况
* </p>
* @param loginName
* @param appServer
* @param client
* @param login
* @throws IOException,HttpException,BusinessServletException
*/
private void dealWithRedirect4LoginDomino(String loginName, AppServer appServer, HttpClient client, PostMethod login)
throws IOException, HttpException, BusinessServletException {
Header header = login.getResponseHeader("location");
login.releaseConnection();
if (header != null) {
String newuri = header.getValue();
newuri = ((newuri == null || newuri.equals("")) ? "/" : newuri);
GetMethod redirect = new GetMethod(newuri);
try {
int statusCode = client.executeMethod(redirect);
if (statusCode != HttpStatus.SC_OK) {
throw new BusinessServletException(appServer.getName()
+ "(" + appServer.getCode() + ")连接错误,错误代码:" + statusCode);
}
dealWithLoginResponse4Domino(loginName, appServer, redirect);
} finally {
redirect.releaseConnection();
}
} else {
throw new BusinessServletException(appServer.getName() + "(" + appServer.getCode() + ")返回错误的自动转向信息");
}
}
/**
* <p>
* 处理登录Domino请求返回数据,判断是否登录,如果没有登录,抛出错误信息。
* 登陆成功返回数据中有 "Success" 字样,可根据这个来判断。
* </p>
*
* @param loginName
* @param appServer
* @param httpMethod
* @throws IOException
* @throws BusinessServletException
*/
private void dealWithLoginResponse4Domino(String loginName,
AppServer appServer, HttpMethod httpMethod) throws IOException, BusinessServletException {
String result = httpMethod.getResponseBodyAsString();
if (result.indexOf(appServer.getOnlineValidationCode()) < 0) {
throw new BusinessServletException("用户不能登录" + appServer.getName()
+ "(" + appServer.getCode() + "),请重新输入该系统用户(" + loginName + ")的密码", 2);
}
}
/**
* <p>
* 验证用户是否已经登录Domino服务器
* </p>
* @param appServer
* @return
*/
private boolean validateIdentity4Domino(AppServer appServer) throws IOException, BusinessServletException {
// 创建HttpClient对象
HttpClient client = HttpClientHelper.instance().getHttpClient(appServer);
GetMethod online = new GetMethod(appServer.getBaseURL() + appServer.getOnlineAction());
try {
int statusCode = client.executeMethod(online);
log.debug("LoginDomino:Do Online Action(" + statusCode + ")");
if (statusCode == HttpStatus.SC_OK) {
String result = online.getResponseBodyAsString();
if (result.indexOf(appServer.getOnlineValidationCode()) > -1) {
log.debug("LoginDomino:Domino Server 已经在线!");
return true;
}
} else {
throw new BusinessServletException(appServer.getName() + "("
+ appServer.getCode() + ")连接错误,错误代码:" + statusCode);
}
} finally {
online.releaseConnection();
}
log.debug("LoginDomino:Domino Server 当前状态为离线!");
return false;
}
}