/* ================================================================== * 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; } }