/* ================================================================== * 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 java.net.URLDecoder; import java.util.Enumeration; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpState; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.InputStreamRequestEntity; import org.apache.commons.httpclient.methods.PostMethod; import com.jinhe.tss.core.exception.BusinessServletException; import com.jinhe.tss.core.sso.appserver.AppServer; import com.jinhe.tss.core.sso.context.Context; import com.jinhe.tss.core.sso.context.RequestContext; import com.jinhe.tss.core.web.RewriteableHttpServletRequest; /** * <p> HttpClientHelper.java </p> * */ public class HttpClientHelper { private HttpClientHelper() { } private static HttpClientHelper helper; public static HttpClientHelper instance(){ if(helper == null){ helper = new HttpClientHelper(); } return helper; } /** 请求超时时间(毫秒数) */ public static final int HTTP_REQUEST_TIMEOUT = 30000; // 30秒 /** Post请求时,Method值 */ public static final String POST_METHOD = "POST"; /** HTTP请求类型参数名 */ public static final String CONTENT_TYPE = "Content-Type"; /** * <p> * 初始化HttpClient对象 * </p> * @return */ public HttpClient getHttpClient() { HttpClient client = new HttpClient(); // 设置Cookie处理策略,RFC_2109是支持较普遍的一个,还有其他cookie协议 client.getParams().setCookiePolicy(CookiePolicy.RFC_2109); // 设置超时时间 MultiThreadedHttpConnectionManager hcm = new MultiThreadedHttpConnectionManager(); hcm.getParams().setConnectionTimeout(HTTP_REQUEST_TIMEOUT); client.setHttpConnectionManager(hcm); return client; } /** * <p> * 初始化HttpClient对象,同时设置转发应用的Cookie信息。 * 将当前请求中的cookie信息(除去sessionId cookie 和 token cookie)设置到新的请求中来 * </p> * @param targetAppServer 转发的目标应用 * @return */ public HttpClient getHttpClient(AppServer targetAppServer) { HttpState initialState = new HttpState(); HttpServletRequest request = Context.getRequestContext().getRequest(); javax.servlet.http.Cookie[] cookies = request.getCookies(); if (cookies != null) { // 设置转发Cookies信息 AppServer currentAppServer = Context.getApplicationContext().getCurrentAppServer(); for (int i = 0; i < cookies.length; i++) { String cookieName = cookies[i].getName(); if (cookieName.equals(currentAppServer.getSessionIdName()) || cookieName.equals(RequestContext.USER_TOKEN)) { continue; } //保存当前应用以为得sessionId信息的cookie一般是以其应用Code命名的,当前应用的则以JSESSIONID命名 if (cookieName.equals(targetAppServer.getCode())) { cookieName = targetAppServer.getSessionIdName(); } Cookie cookie = new Cookie(targetAppServer.getDomain(), cookieName, cookies[i].getValue(), targetAppServer.getPath(), null, request.isSecure()); initialState.addCookie(cookie); } } HttpClient client = this.getHttpClient(); client.setState(initialState); client.getParams().setParameter("http.protocol.single-cookie-header", targetAppServer.isSingleCookieHeader()); return client; } /** * <p> * 初始化HttpMethod对象。 * 转发的时候把第一次转发过来header头带的appCode值去掉,理论上不会有二次转发的可能。 * </p> * @param appServer * @return * @throws IOException * @throws BusinessServletException */ public HttpMethod getHttpMethod(AppServer appServer) throws IOException, BusinessServletException { RequestContext requestContext = Context.getRequestContext(); HttpServletRequest request = requestContext.getRequest(); // 并初始化QueryString参数 String realPath = requestContext.getRealPath(); String queryString = null; if (realPath == null || "".equals(realPath)) { realPath = request.getRequestURI().substring(request.getContextPath().length()); queryString = request.getQueryString(); } else { realPath = URLDecoder.decode(realPath, "UTF-8"); int index = realPath.indexOf("?"); if (index > -1) { realPath = realPath.substring(0, index); queryString = realPath.substring(index + 1); } } String newurl = appServer.getBaseURL() + realPath; // 根据请求类型创建请求代理 HttpMethod httpMethod; if (POST_METHOD.equalsIgnoreCase(request.getMethod())) { // POST httpMethod = new PostMethod(newurl); // 设置请求内容,将原请求中的数据流转给新的请求 InputStreamRequestEntity requestEntity = new InputStreamRequestEntity(request.getInputStream(), request.getContentType()); ((PostMethod)httpMethod).setRequestEntity(requestEntity); } else { // GET httpMethod = new GetMethod(newurl); } // 设置QueryString参数 if (queryString != null && !"".equals(queryString)) { httpMethod.setQueryString(queryString); } // 设置请求头参数 @SuppressWarnings("unchecked") Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String value = request.getHeader(name); // 转发的时候去掉header中 cookie(下面单独转发) 和 appCode(转发后不再需要) if ("cookie".equalsIgnoreCase(name) || "appCode".equalsIgnoreCase(name)) continue; httpMethod.setRequestHeader(name, value); } // 设置用户令牌 if (Context.isOnline()){ httpMethod.setRequestHeader(RequestContext.USER_TOKEN, Context.getToken()); } // 设置客户端IP httpMethod.setRequestHeader(RequestContext.USER_CLIENT_IP, requestContext.getClientIp()); return httpMethod; } /** * 处理二次转发请求(request2)转发成功后 返回的Cookie信息,将这些cookie设置到初始的请求和响应里 * @param cookies * 注:是org.apache.commons.httpclient.Cookie * @param targetAppServer */ public static void transmitReturnCookies(org.apache.commons.httpclient.Cookie[] cookies, AppServer targetAppServer) { RequestContext requestContext = Context.getRequestContext(); if (requestContext == null) { return; } RewriteableHttpServletRequest request = requestContext.getRequest(); HttpServletResponse response = Context.getResponse(); if (response == null || request == null) { return; } // 转发返回Cookies for (int i = 0; i < cookies.length; i++) { String cookieName = cookies[i].getName(); //如果当前应用本身的cookie,则无需转发 if (cookieName.equals(Context.getApplicationContext().getCurrentAppCode())) continue; if (cookieName.equals(targetAppServer.getSessionIdName())) { cookieName = targetAppServer.getCode(); } javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(cookieName, cookies[i].getValue()); cookie.setPath(request.getContextPath()); cookie.setMaxAge(-1); cookie.setSecure(request.isSecure()); if (response.isCommitted()) { response.addCookie(cookie); } request.addCookie(cookie); // 同时也添加到request中,以用于二次、三次的远程接口调用 } } }