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

com.alogic.oauth.client.DefaultOAuthServer Maven / Gradle / Ivy

package com.alogic.oauth.client;

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.oauth.OAuthConstants;
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.message.JsonMessage;
import com.logicbus.backend.server.http.HttpContext;

/**
 * 缺省的OAuth2.0服务器实现
 * 
 * @author yyduan
 * @since 1.6.11.61
 * @version 1.6.12.7 [20181108 duanyy] 
* - 优化oauth2.0的客户端流程
* * @version 1.6.12.8 [20181121 duanyy]
* - 优化oauth客户端处理
* * @version 1.6.12.9 [20181127 duanyy]
* - 采用HttpClientTool来获取客户端ip
* * @version 1.6.12.17 [20181229 duanyy]
* - doLoginCallback和doBindCallback增加$callbackUrl脚本变量
* * @version 1.6.12.36 [20190611 duanyy]
* - 增加bizlog输出
* * @version 1.6.14.13 [20210708 duanyy]
* - 优化callback路径的拼接逻辑
*/ public class DefaultOAuthServer implements OAuthServer{ /** * a logger of slf4j */ protected final static Logger LOG = LoggerFactory.getLogger(OAuthServer.class); /** * OAuth2.0服务器的id */ protected String id; /** * 当发起登录授权时所调用的脚本 */ protected Logiclet onLoginRequest = null; /** * 当发起登录授权之后回调所调用的脚本 */ protected Logiclet onLoginCallback = null; /** * 当发起帐号绑定授权时所调用的脚本 */ protected Logiclet onBindRequest = null; /** * 当发起帐号绑定授权之后回调所调用的脚本 */ protected Logiclet onBindCallback = null; /** * 扩展指令 */ protected Logiclet onCommand = null; /** * 服务器端进行授权的URL地址 */ protected String urlAuthorize = "${oauth.server}/oauth/authorize"; /** * 服务器端进行授权的URL地址 */ protected String urlAccessToken = "${oauth.server}/oauth/access_token"; /** * CAS服务器的回调路径 */ protected String callbackPath = "/oauthclient/callback/${id}"; /** * 回调服务器地址 */ protected String callbackServer = ""; /** * 时间戳 */ private long timestamp = System.currentTimeMillis(); /** * 编码 */ protected String encoding = "utf-8"; protected String sessionGroup = "$oauth-client"; /** * 在oauth服务器上的clientId */ protected String clientId = ""; /** * 在oauth服务器上的Secrect */ protected String clientSecret = ""; protected HttpClientTool httpClientTool = null; /** * 内部跳转URL的参数 */ protected String returnURL = OAuthConstants.ARGU_RETURNURL; /** * 缺省的主页URL */ protected String mainPage = "/"; 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); } @Override public String getId() { return id; } @Override public boolean isOk() { return StringUtils.isNotEmpty(id); } /** * 获取生存时间(毫秒) * @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", ""); returnURL = PropertiesConstants.getString(props,"auth.para.url",returnURL); mainPage = PropertiesConstants.getString(props,"auth.page.main",mainPage); clientId = PropertiesConstants.getString(props, "clientId", clientId); clientSecret = PropertiesConstants.getString(props, "clientSecret", clientSecret); urlAuthorize = PropertiesConstants.getString(props, "urlAuthorize", urlAuthorize); urlAccessToken = PropertiesConstants.getString(props, "urlAccessToken", urlAccessToken); callbackPath = PropertiesConstants.getString(props, "callbackPath", callbackPath); callbackServer = PropertiesConstants.getString(props, "callbackServer", callbackServer); encoding = PropertiesConstants.getString(props,"http.encoding",encoding); sessionGroup = PropertiesConstants.getString(props, "oauth.client.group",sessionGroup); httpClientTool = Settings.getToolkit(HttpClientTool.class); if (onLoginRequest == null){ String script = PropertiesConstants.getString(props, "on-login-request",""); if (StringUtils.isNotEmpty(script)){ onLoginRequest = Script.createFromContent(script, props); } } if (onBindRequest == null){ String script = PropertiesConstants.getString(props, "on-bind-request",""); if (StringUtils.isNotEmpty(script)){ onBindRequest = Script.createFromContent(script, props); } } if (onLoginCallback == null){ String script = PropertiesConstants.getString(props, "on-login-callback",""); if (StringUtils.isNotEmpty(script)){ onLoginCallback = Script.createFromContent(script, props); } } if (onBindCallback == null){ String script = PropertiesConstants.getString(props, "on-bind-callback",""); if (StringUtils.isNotEmpty(script)){ onBindCallback = Script.createFromContent(script, props); } } if (onCommand == null){ String script = PropertiesConstants.getString(props, "on-command",""); if (StringUtils.isNotEmpty(script)){ onCommand = Script.createFromContent(script, props); } } } @Override public void configure(Element e, Properties p) { Properties props = new XmlElementProperties(e,p); Element elem = XmlTools.getFirstElementByPath(e, "on-login-request"); if (elem != null){ onLoginRequest = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-bind-request"); if (elem != null){ onBindRequest = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-login-callback"); if (elem != null){ onLoginCallback = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-bind-callback"); if (elem != null){ onBindCallback = Script.create(elem, props); } configure(props); } protected Session getSession(SessionManager sm,HttpServletRequest request,HttpServletResponse response,boolean create){ return sm.getSession(request,response,create); } protected String getCallbackPath(HttpServletRequest httpReq,HttpServletResponse httpResp, Session session,String action){ StringBuffer callback = new StringBuffer(); if (StringUtils.isNotEmpty(callbackServer)){ callback.append(callbackServer); }else{ callback.append(httpClientTool.getContextBase(httpReq)); } callback.append(callbackPath).append("/").append(action); return callback.toString(); } @Override public void doLoginRequest(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { if (onLoginRequest != 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); XsObject doc = new JsonObject("root", new HashMap()); String callback = getCallbackPath(httpReq,httpResp,sess,"login"); logicletContext.SetValue("$callbackUrl", callback); logicletContext.SetValue("$authorizeUrl", this.urlAuthorize); logicletContext.SetValue("$clientId", this.clientId); logicletContext.SetValue("$clientSecret", this.clientSecret); logicletContext.SetValue("$service", "/oauth2/client/Login"); logicletContext.SetValue("$clientIp",clientIp); onLoginRequest.execute(doc, doc, logicletContext, null); String redirectUrl = PropertiesConstants.getString(logicletContext,"$authorizeUrl",this.urlAuthorize); try { //客户端模式,重定向到服务端 if (StringUtils.isNotEmpty(redirectUrl)){ httpClientTool.sendRedirect(httpResp,redirectUrl); } } catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } } finally { logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/oauth2/client/Login",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } }else{ throw new BaseException("core.e1000","Oauth login is not supported now."); } } @Override public void doBindRequest(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { if (onBindRequest != 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); XsObject doc = new JsonObject("root", new HashMap()); String callback = getCallbackPath(httpReq,httpResp,sess,"bind"); logicletContext.SetValue("$callbackUrl", callback); logicletContext.SetValue("$authorizeUrl", this.urlAuthorize); logicletContext.SetValue("$clientId", this.clientId); logicletContext.SetValue("$clientSecret", this.clientSecret); logicletContext.SetValue("$service", "/oauth2/client/Bind"); logicletContext.SetValue("$clientIp",clientIp); onBindRequest.execute(doc, doc, logicletContext, null); String redirectUrl = PropertiesConstants.getString(logicletContext,"$authorizeUrl",this.urlAuthorize); try { //客户端模式,重定向到服务端 if (StringUtils.isNotEmpty(redirectUrl)){ httpClientTool.sendRedirect(httpResp,redirectUrl); } } catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } } finally { logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/oauth2/client/Bind",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } }else{ throw new BaseException("core.e1000","Oauth login is not supported now."); } } @Override public void doLoginCallback(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { if (onLoginCallback != 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); String callback = getCallbackPath(httpReq,httpResp,sess,"login"); logicletContext.SetValue("$callbackUrl", callback); logicletContext.SetValue("$accesstokenUrl", this.urlAccessToken); logicletContext.SetValue("$clientId", this.clientId); logicletContext.SetValue("$clientSecret", this.clientSecret); logicletContext.SetValue("$service", "/oauth2/client/LoginCallback"); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root", new HashMap()); onLoginCallback.execute(doc, doc, logicletContext, null); String redirectUrl = PropertiesConstants.getString(logicletContext,"$nextUrl",this.mainPage); try { //客户端模式,重定向到服务端 if (StringUtils.isNotEmpty(redirectUrl)){ httpClientTool.sendRedirect(httpResp,redirectUrl); } } catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } return ; } finally { logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/oauth2/client/LoginCallback",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } } @Override public void doBindCallback(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { if (onBindCallback != 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); String callback = getCallbackPath(httpReq,httpResp,sess,"bind"); logicletContext.SetValue("$callbackUrl", callback); logicletContext.SetValue("$accesstokenUrl", this.urlAccessToken); logicletContext.SetValue("$clientId", this.clientId); logicletContext.SetValue("$clientSecret", this.clientSecret); logicletContext.SetValue("$service", "/oauth2/client/BindCallback"); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root", new HashMap()); onBindCallback.execute(doc, doc, logicletContext, null); String redirectUrl = PropertiesConstants.getString(logicletContext,"$nextUrl",this.mainPage); try { //客户端模式,重定向到服务端 if (StringUtils.isNotEmpty(redirectUrl)){ httpClientTool.sendRedirect(httpResp,redirectUrl); } } catch (Exception ex){ LOG.error(ExceptionUtils.getStackTrace(ex)); } return ; } finally { logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/oauth2/client/BindCallback",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } } @Override public void doCommand(HttpServletRequest httpReq, HttpServletResponse httpResp, SessionManager sm, Session session) { Context ctx = new HttpContext(httpReq, httpResp, encoding); JsonMessage msg = (JsonMessage)ctx.asMessage(JsonMessage.class); try { if (onCommand != null) { 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("$accesstokenUrl", this.urlAccessToken); logicletContext.SetValue("$clientId", this.clientId); logicletContext.SetValue("$clientSecret", this.clientSecret); logicletContext.SetValue("$service", "/oauth2/client/Command"); logicletContext.SetValue("$clientIp",clientIp); XsObject doc = new JsonObject("root",msg.getRoot()); onCommand.execute(doc, doc, logicletContext, null); } finally { logicletContext.removeObject(ID_SESSION); logicletContext.removeObject(ID_COOKIES); bizlog("/oauth2/client/Command",clientIp,System.currentTimeMillis(),System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } }catch (BaseException ex){ ctx.setReturn(HttpServletResponse.SC_OK,ex.getCode(), ex.getMessage()); }catch (Exception ex){ ctx.setReturn(HttpServletResponse.SC_OK,"core.e1012",ex.getMessage()); }catch (Throwable t){ ctx.setReturn(HttpServletResponse.SC_OK,"core.e1012",t.getMessage()); } finally { ctx.setEndTime(System.nanoTime()); ctx.finish(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy