All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alogic.cas.client.DefaultCasServer Maven / Gradle / Ivy

package com.alogic.cas.client;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.anysoft.webloader.HttpClientTool;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import com.alogic.auth.CookieManager;
import com.alogic.auth.Session;
import com.alogic.auth.SessionManager;
import com.alogic.remote.util.HttpQuery;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.Script;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.doc.json.JsonObject;
import com.anysoft.util.BaseException;
import com.anysoft.util.JsonTools;
import com.anysoft.util.KeyGen;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Settings;
import com.anysoft.util.XmlElementProperties;
import com.anysoft.util.XmlTools;
import com.logicbus.backend.Context;
import com.logicbus.backend.bizlog.BizLog;
import com.logicbus.backend.server.http.HttpContext;

/**
 * CasServer的缺省实现
 * 
 * @author yyduan
 * @since 1.6.11.60 [20180912 duanyy] 
 * 
 * @version 1.6.11.61 [20180913 duanyy] 
* - 增加$service和$clientIp等内置变量
* * @version 1.6.12.8 [20181121 duanyy]
* - 优化cas客户端处理
* * @version 1.6.12.9 [20181127 duanyy]
* - 采用HttpClientTool来获取客户端ip
* * @version 1.6.12.36 [20190611 duanyy]
* - 增加bizlog输出
* * @version 1.6.12.41 [20190902]
* - 修正bug
* * @version 1.6.13.4 [20200514 duanyy]
* - 修正环境变量拼写错误 * * @version 1.6.14.13 [20210708 duanyy]
* - 优化callback路径的拼接逻辑
*/ public class DefaultCasServer implements CasServer { /** * a logger of slf4j */ protected final static Logger LOG = LoggerFactory.getLogger(CasServer.class); /** * Server id */ protected String id; /** * CAS服务器的登录地址 */ protected String loginURL = "${cas.server}/login"; /** * CAS服务器的token验证地址 */ protected String validateURL = "${cas.server}/serviceValidate"; /** * CAS服务器的登出地址 */ protected String logoutURL = "${cas.server}/logout"; /** * CAS服务器的回调路径 */ protected String callbackPath = "/casclient/cas/${id}"; /** * 回调服务器地址 */ protected String callbackServer = ""; /** * ticket参数名 */ protected String arguTicket = "ticket"; /** * service参数名 */ protected String arguService = "service"; /** * 编码 */ protected String encoding = "utf-8"; /** * 当验证token时执行脚本 */ protected Logiclet onValidate = null; /** * 当注销时执行脚本 */ protected Logiclet onLogout = null; /** * 当注销时执行脚本 */ protected Logiclet onLogoutCallback = null; /** * 当登录时执行脚本 */ protected Logiclet onLogin = null; /** * 时间戳 */ private long timestamp = System.currentTimeMillis(); protected String sessionGroup = "$cas-client"; protected HttpClientTool httpClientTool = null; public void bizlog(String service,String clientIp,long time,long duration,String url,boolean error,String reason){ BizLog.log(KeyGen.uuid(8,0,15),service,clientIp,error?CODE_ERR:CODE_OK,reason,time,duration,url); } /** * 获取生存时间(毫秒) * @return 生存时间 */ protected long getTTL(){ return 5 * 60 * 1000L; } @Override public long getTimestamp() { return timestamp; } @Override public boolean isExpired() { return System.currentTimeMillis() - this.timestamp > getTTL(); } @Override public void expire() { this.timestamp = System.currentTimeMillis() - getTTL(); } @Override public void report(Element xml) { if (xml != null){ XmlTools.setString(xml,"module",getClass().getName()); } } @Override public void report(Map json) { if (json != null){ JsonTools.setString(json,"module",getClass().getName()); } } @Override public void configure(Properties props) { id = PropertiesConstants.getString(props, "id", ""); loginURL = PropertiesConstants.getString(props, "cas.server.login", loginURL); validateURL = PropertiesConstants.getString(props, "cas.server.validate", validateURL); logoutURL = PropertiesConstants.getString(props, "cas.server.logout", logoutURL); callbackPath = PropertiesConstants.getString(props, "cas.callback.path", callbackPath); callbackServer = PropertiesConstants.getString(props, "cas.callback.server", callbackServer); arguTicket = PropertiesConstants.getString(props, "cas.para.ticket", arguTicket); arguService = PropertiesConstants.getString(props, "cas.para.service", arguService); encoding = PropertiesConstants.getString(props,"http.encoding",encoding); sessionGroup = PropertiesConstants.getString(props, "cas.client.group",sessionGroup); httpClientTool = Settings.getToolkit(HttpClientTool.class); if (onValidate == null){ String script = PropertiesConstants.getString(props, "onValidate",""); if (StringUtils.isNotEmpty(script)){ onValidate = Script.createFromContent(script, props); } } if (onLogout == null){ String script = PropertiesConstants.getString(props, "onLogout",""); if (StringUtils.isNotEmpty(script)){ onLogout = Script.createFromContent(script, props); } } if (onLogin == null){ String script = PropertiesConstants.getString(props, "onLogin",""); if (StringUtils.isNotEmpty(script)){ onLogin = Script.createFromContent(script, props); } } if (onLogoutCallback == null){ String script = PropertiesConstants.getString(props, "onLogoutCallback",""); if (StringUtils.isNotEmpty(script)){ onLogoutCallback = Script.createFromContent(script, props); } } } @Override public void configure(Element e, Properties p) { Properties props = new XmlElementProperties(e,p); Element elem = XmlTools.getFirstElementByPath(e, "on-validate"); if (elem != null){ onValidate = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-logout"); if (elem != null){ onLogout = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-logout-callback"); if (elem != null){ onLogoutCallback = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-login"); if (elem != null){ onLogin = Script.create(elem, props); } configure(props); } @Override public String getId() { return id; } @Override public boolean isOk() { return StringUtils.isNotEmpty(id); } @Override public void doLogoutCallback(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session, String sessionId) { LOG.info("Call back from cas server.." + httpReq.getRemoteAddr()); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { if (onLogoutCallback != null){ Context ctx = new HttpContext(httpReq,httpResp,encoding); Session sess = getSession(sm,httpReq,httpResp, true); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); CookieManager cm = new CookieManager.Default(sm, httpReq, httpResp); try { logicletContext.setObject(ID_SESSION, sess); logicletContext.setObject(ID_COOKIES, cm) ; logicletContext.SetValue("$service", "/cas/client/LogoutCallback"); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root",new HashMap()); onLogoutCallback.execute(doc,doc, logicletContext, null); }finally{ logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); } } if (StringUtils.isNotEmpty(sessionId)){ LOG.info("Clear session:" + sessionId); sm.delSession(sessionId); } }finally{ bizlog("/cas/client/LogoutCallback",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } @Override public void doValidate(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { //由sso服务器进行回调 String token = this.getParameter(httpReq, arguTicket, ""); if (StringUtils.isNotEmpty(token)){ //参数中指定了新的token String oldToken = session.hGet(sessionGroup, Session.TOKEN, ""); if (!token.equals(oldToken)){ //记录token到当前的session session.hSet(sessionGroup, Session.TOKEN, token, true); } }else{ token = session.hGet(sessionGroup, Session.TOKEN, ""); } if (StringUtils.isEmpty(token)){ throw new BaseException("clnt.e2000","Cas ticket is not found."); } if (onValidate != null){ Context ctx = new HttpContext(httpReq,httpResp,encoding); Session sess = getSession(sm,httpReq,httpResp, true); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); CookieManager cm = new CookieManager.Default(sm, httpReq, httpResp); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { String service = getCasService(httpReq,httpResp,session); //调用远程服务来验证token HttpQuery query = new HttpQuery(validateURL); query.param(this.arguTicket, token); query.param(this.arguService, service); String validateEndpoint = query.toString(); logicletContext.setObject(ID_SESSION, sess); logicletContext.setObject(ID_COOKIES, cm) ; logicletContext.SetValue(ID_CAS_TICKET, token); logicletContext.SetValue(ID_CAS_SERVICE, service); logicletContext.SetValue(ID_CAS_VALIDATE_PATH, validateURL); logicletContext.SetValue(ID_CAS_VALIDATE_ENDPOINT, validateEndpoint); logicletContext.SetValue("$service", "/cas/client/Validate"); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root",new HashMap()); onValidate.execute(doc,doc, logicletContext, null); }finally{ logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/cas/client/Validate",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } } @Override public void doLogout(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { String nextUrl = logoutURL; if (onLogout != null){ Context ctx = new HttpContext(httpReq,httpResp,encoding); Session sess = getSession(sm,httpReq,httpResp, true); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); CookieManager cm = new CookieManager.Default(sm, httpReq, httpResp); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { logicletContext.setObject(ID_SESSION, sess); logicletContext.setObject(ID_COOKIES, cm) ; logicletContext.SetValue("$service", "/cas/client/Logout"); logicletContext.SetValue("$nextUrl", nextUrl); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root",new HashMap()); onLogout.execute(doc,doc, logicletContext, null); nextUrl = PropertiesConstants.getString(ctx, "$nextUrl", nextUrl); }finally{ logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/cas/client/Logout",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } try { //客户端模式,重定向到服务端 if (StringUtils.isNotEmpty(nextUrl)){ httpClientTool.sendRedirect(httpResp,nextUrl); } } catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } } @Override public void doLogin(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { String callback = getCasService(httpReq,httpResp,session); try { String nextUrl = String.format("%s?%s=%s", loginURL,arguService,URLEncoder.encode(callback,encoding)); if (onLogin != null){ Context ctx = new HttpContext(httpReq,httpResp,encoding); Session sess = getSession(sm,httpReq,httpResp, true); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); CookieManager cm = new CookieManager.Default(sm, httpReq, httpResp); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { logicletContext.setObject(ID_SESSION, sess); logicletContext.setObject(ID_COOKIES, cm) ; logicletContext.SetValue("$service", "/cas/client/Login"); logicletContext.SetValue("$clientIp",clientIp); logicletContext.SetValue("$nextUrl", nextUrl); logicletContext.SetValue("$cas-service", callback); XsObject doc = new JsonObject("root",new HashMap()); onLogin.execute(doc,doc, logicletContext, null); nextUrl = PropertiesConstants.getString(logicletContext, "$nextUrl", nextUrl); }finally{ logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/cas/client/Login",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } LOG.info("User has not logged in,redirect to: " + nextUrl); httpClientTool.sendRedirect(httpResp,nextUrl); }catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } } protected Session getSession(SessionManager sm,HttpServletRequest request,HttpServletResponse response,boolean create){ return sm.getSession(request,response,create); } protected String getCasService(HttpServletRequest httpReq,HttpServletResponse httpResp, Session session) { StringBuffer callback = new StringBuffer(); if (StringUtils.isNotEmpty(callbackServer)){ callback.append(callbackServer).append(httpReq.getContextPath()); }else{ callback.append(httpClientTool.getContextBase(httpReq)); } callback.append(callbackPath).append("/").append(session.getId()); return callback.toString(); } /** * 从Request中获取指定的参数 * @param request HttpServletRequest * @param id 参数id * @param dftValue 缺省值,当参数不存在时,返回 * @return 参数值,如果参数不存在,返回缺省值 */ protected String getParameter(HttpServletRequest request,String id,String dftValue){ String value = request.getParameter(id); return StringUtils.isEmpty(value)?dftValue:value; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy