package org.quickbundle.project.login;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.dom4j.Element;
import org.quickbundle.base.exception.RmRuntimeException;
import org.quickbundle.base.vo.RmValueObject;
import org.quickbundle.config.RmClusterConfig;
import org.quickbundle.config.RmLoadConfig;
import org.quickbundle.project.IGlobalConstants;
import org.quickbundle.project.secure.RmCryptoHelper;
import org.quickbundle.tools.helper.RmStringHelper;
import org.quickbundle.tools.helper.RmUUIDHelper;
import org.quickbundle.tools.support.encrypt.Md5Token;
import org.quickbundle.tools.support.log.RmLogHelper;
import org.slf4j.Logger;
public class RmSsoLogin {
private static final Logger log = RmLogHelper.getLogger(RmSsoLogin.class);
public final static String ssoKey = "rm_sso";
public final static String splictKey = "$";
public final static String splictKeyRegex = "\\$";
public final static long defaultExpired = 1000 * 60 * 30;
private static String privateKey = RmUUIDHelper.generateUUID();
/**
* 处理待跳转的url
* @param request
* @param response
* @param filterChain
* @throws IOException
*/
public static boolean doRedirectUrl(ServletRequest request, ServletResponse response, FilterChain filterChain, String pUrl) {
try {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
Element thisNode = null;
for(Object nodeObj : RmLoadConfig.getRmClusterDoc().selectNodes("/rm/org.quickbundle.project.login.RmSsoLogin/redirectGroup[@enable='true']/redirectUrls/url")) {
Element node = (Element)nodeObj;
if(node.getText().equals(pUrl)) {
thisNode = node;
break;
}
}
if(thisNode == null) {
throw new RmRuntimeException("配置文件读取错误");
}
String targetUrlPrefix = null;
for(Object baseUrlObj : thisNode.selectNodes("../../redirectTargets/baseUrl")) {
//TODO 可扩展为负载均衡算法
Element eleUrlPrefix = (Element)baseUrlObj;
targetUrlPrefix = eleUrlPrefix.getText();
break;
}
if(targetUrlPrefix.length() == 0) {
throw new RmRuntimeException("未配置跳转到的目标地址");
}
//带着sso信息跳转到目标服务器
if(RmClusterConfig.getLocalhostInfo() != null
&& targetUrlPrefix.startsWith(RmClusterConfig.getLocalhostInfo().getLocalhostUrlPath())) {
//throw new RmRuntimeException("不能跳转到自身,可能导致循环跳转");
//如果判断为跳到本机,忽略跳转
filterChain.doFilter(request, response);
return true;
}
res.sendRedirect(rebuildUri(req, targetUrlPrefix));
return true;
} catch (Exception e) {
log.error("doRedirectUrl():" + e.toString() + " cause:" + e.getCause());
//save error
request.setAttribute("org.apache.struts.action.EXCEPTION", e);
return false;
}
}
static String rebuildUri(HttpServletRequest request, String redirectUrlPrefix) {
HttpSession session = ((HttpServletRequest)request).getSession(true);
StringBuilder url = new StringBuilder();
if(redirectUrlPrefix.endsWith("/")) {
redirectUrlPrefix = redirectUrlPrefix.substring(0, redirectUrlPrefix.length()-1);
}
url.append(redirectUrlPrefix);
String uri = request.getRequestURI().substring(request.getContextPath().length());
url.append(uri);
url.append("?");
if(request.getQueryString() != null) {
url.append(request.getQueryString());
url.append("&");
}
url.append(ssoKey);
url.append("=");
try {
url.append(RmStringHelper.encodeUrl(RmCryptoHelper.encryptDesBase64(RmSsoLogin.createInstance(session.getId()).toString())));
} catch (Exception e) {
e.printStackTrace();
}
return url.toString();
}
public static boolean doSsoLogin(ServletRequest request, ServletResponse response, FilterChain filterChain) {
try {
HttpSession session = ((HttpServletRequest)request).getSession(true);
//临时登录超时时间
session.setMaxInactiveInterval(60 * 3);
String ssoValue = request.getParameter(ssoKey);
try {
ssoValue = RmCryptoHelper.decryptDesBase64(ssoValue);
} catch (Exception e) {
e.printStackTrace();
}
String[] ssoValueArgs = ssoValue.split(splictKeyRegex);
String nodeId = ssoValueArgs[0];
String sessionId = ssoValueArgs[2];
String callWsUrl = RmClusterConfig.getSingleton().getSelfNode().get(RmClusterConfig.NodeKey.webServiceUrl.name());
String address = callWsUrl + "RmSsoLogin";
JaxWsProxyFactoryBean jw = new JaxWsProxyFactoryBean();
jw.setServiceClass(IRmSsoService.class);
jw.setAddress(address);
Object obj = jw.create();
IRmSsoService ssoService = (IRmSsoService) obj;
RmUserVo userVo = ssoService.copyLogin(sessionId, ssoValue);
session.setAttribute(IGlobalConstants.RM_USER_VO, userVo);
session.setAttribute(IGlobalConstants.RM_SSO_TEMP, IGlobalConstants.RM_YES);
return true;
} catch (Exception e) {
log.error("doSsoLogin():" + e.toString() + " cause:" + e.getCause());
//save error
request.setAttribute("org.apache.struts.action.EXCEPTION", e);
return false;
}
}
public static RmSsoVo createInstance(String sessionId) {
RmSsoVo instance = new RmSsoVo();
instance.setNodeId(RmClusterConfig.getSingleton().getSelfId());
instance.setExpired(String.valueOf(System.currentTimeMillis() + defaultExpired));
instance.setSessionId(sessionId);
instance.setHash(Md5Token.getInstance().getLongToken(Md5Token.getInstance().getLongToken(instance.nodeId + instance.expired + instance.sessionId) + privateKey));
return instance;
}
public static class RmSsoVo extends RmValueObject {
private RmSsoVo() {
}
public RmSsoVo(String ssoValue) {
String[] args = ssoValue.split(splictKeyRegex);
nodeId = args[0];
expired = args[1];
sessionId = args[2];
hash = args[3];
}
public boolean validateSsoVo() {
String hash_ = Md5Token.getInstance().getLongToken(Md5Token.getInstance().getLongToken(nodeId + expired + sessionId) + privateKey);
if(hash_.equals(hash)) {
return true;
} else {
return false;
}
}
private String nodeId;
private String expired;
private String sessionId;
private String hash;
/**
* @return the nodeId
*/
public String getNodeId() {
return nodeId;
}
/**
* @param nodeId the nodeId to set
*/
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
/**
* @return the expired
*/
public String getExpired() {
return expired;
}
/**
* @param expired the expired to set
*/
public void setExpired(String expired) {
this.expired = expired;
}
/**
* @return the sessionId
*/
public String getSessionId() {
return sessionId;
}
/**
* @param sessionId the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* @return the hash
*/
public String getHash() {
return hash;
}
/**
* @param hash the hash to set
*/
public void setHash(String hash) {
this.hash = hash;
}
@Override
public String toString() {
return nodeId + splictKey + expired + splictKey + sessionId + splictKey + hash;
}
}
public static void main(String[] args) {
try {
String value = "中国";
// byte[] tmp = RmProjectHelper.encrypt(value.getBytes(), desKey.getBytes());
// System.out.println(new String(tmp));
// System.out.println(Base64.encodeBase64String(tmp));
// System.out.println(new String());
// System.out.println(new String(RmProjectHelper.decrypt(Base64.decodeBase64(Base64.encodeBase64String(tmp)), desKey.getBytes())));
value = RmCryptoHelper.encryptDesBase64(value);
System.out.println(value);
System.out.println(RmCryptoHelper.decryptDesBase64(value));
value = "我爱北京天安门34";
value = RmCryptoHelper.encryptBase64(value);
System.out.println(value);
System.out.println(RmCryptoHelper.decryptBase64(value));
System.out.println("5oiR54ix5YyX5Lqs5aSp5a6J6ZeoMzQ");
} catch (Exception e) {
e.printStackTrace();
}
}
}