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

com.alogic.bearer.BearerHandler Maven / Gradle / Ivy

package com.alogic.bearer;

import com.alogic.json.JsonFactory;
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.*;
import com.anysoft.util.resource.ResourceFactory;
import com.anysoft.webloader.HttpClientTool;
import com.anysoft.webloader.ServletConfigProperties;
import com.anysoft.webloader.ServletHandler;
import com.logicbus.backend.Context;
import com.logicbus.backend.bizlog.BizLog;
import com.logicbus.backend.server.http.HttpContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Bearer Handler
 *
 * @since 1.6.14.13 [2021708 duanyy]
 *
 * @version 1.6.15.2 [20211103 duanyy] 
* - 在doAuth时注入service变量;
*/ public class BearerHandler implements ServletHandler, XMLConfigurable, Configurable,BearerConstants { /** * a logger of slf4j */ protected final static Logger LOG = LoggerFactory.getLogger(BearerHandler.class); /** * 缺省配置文件 */ protected static final String DEFAULT = "java:///com/alogic/bearer/default.xml#App"; /** * command的前缀 */ protected String cmdPrefix = "/auth"; /** * 获取token的地址 */ protected String realm = "/auth/token"; protected String realmMode = "link"; protected String service = "self"; /** * 编码 */ protected String encoding = "utf-8"; /** * 验证当前token及权限 */ protected Logiclet onAuth = null; /** * 获取token */ protected Logiclet onToken = null; protected HttpClientTool httpClientTool = null; protected static Pattern bearerPattern = Pattern.compile("^Bearer (.+)$"); protected static Pattern basicPattern = Pattern.compile("^Basic (.+)$"); protected static Pattern realmPattern = Pattern.compile("^\\[(\\w*)\\](.+)$"); protected String contentType = "application/json;charset=utf-8"; protected JsonFactory jsonFactory = Settings.getToolkit(JsonFactory.class); 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 void configure(Properties p) { cmdPrefix = PropertiesConstants.getString(p, "cmdPrefix",cmdPrefix); encoding = PropertiesConstants.getString(p, "encoding",encoding); service = PropertiesConstants.getString(p,"service",service); httpClientTool = Settings.getToolkit(HttpClientTool.class); realm = PropertiesConstants.getString(p,"realm",realm); Matcher matcher = realmPattern.matcher(realm); if (matcher.find()){ this.realmMode = matcher.group(1); this.realm = matcher.group(2); } } @Override public void configure(Element e, Properties p) { Properties props = new XmlElementProperties(e,p); configure(props); Element elem = XmlTools.getFirstElementByPath(e, "on-auth"); if (elem != null){ onAuth = Script.create(elem, props); } elem = XmlTools.getFirstElementByPath(e, "on-token"); if (elem != null){ onToken = Script.create(elem, props); } } @Override public void init(ServletConfig servletConfig) throws ServletException { ServletConfigProperties props = new ServletConfigProperties(servletConfig); String master = PropertiesConstants.getString(props, "bearer.server.master", DEFAULT); String secondary = PropertiesConstants.getString(props, "bearer.server.secondary", DEFAULT); ResourceFactory rf = Settings.getResourceFactory(); InputStream in = null; try { in = rf.load(master, secondary, null); Document doc = XmlTools.loadFromInputStream(in); if (doc != null){ configure(doc.getDocumentElement(), props); } }catch (Exception ex){ LOG.error("Can not init bearer handler with file : " + master); }finally{ IOTools.close(in); } } @Override public void doService(HttpServletRequest httpReq, HttpServletResponse httpResp, String method) throws ServletException, IOException { try { String cmd = getCommand(httpReq.getContextPath(),httpReq.getRequestURI()); if (StringUtils.isNotEmpty(cmd)){ if (cmd.startsWith("/token")){ doToken(onToken,httpReq,httpResp); return; } } doAuth(onAuth,httpReq,httpResp); }catch (BaseException ex){ httpClientTool.sendError(httpResp,E404,String.format("%s:%s",ex.getCode(),ex.getMessage())); } } protected void doAuth(Logiclet handler,HttpServletRequest httpReq, HttpServletResponse httpResp) { if (handler == null){ throw new BaseException("core.e1000","Handler on-auth is not defined"); } String token = getBearerToken(httpReq,TOKEN_NULL); Context ctx = new HttpContext(httpReq,httpResp,encoding); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { logicletContext.SetValue("$service", "/bearer/auth"); logicletContext.SetValue("$clientIp",clientIp); logicletContext.SetValue("$token",token); logicletContext.SetValue("service",service); XsObject doc = new JsonObject("root",new HashMap()); handler.execute(doc,doc, logicletContext, null); int status = PropertiesConstants.getInt(logicletContext,"$status",E200); String provider = PropertiesConstants.getString(logicletContext,"service",service); httpClientTool.setStatus(httpResp,status); if (status != E200){ httpClientTool.setResponseHeader(httpResp,HEAD_WWW_AUTHENTICATE, String.format(BEARER,getRealm(httpReq), provider)); } OutputStream out = null; try { String data = jsonFactory.toJsonString(doc.getContent()); ctx.setResponseContentType(contentType); out = ctx.getOutputStream(); byte [] bytes = data.getBytes(ctx.getEncoding()); ctx.setResponseContentLength(bytes.length); Context.writeToOutpuStream(out, bytes); out.flush(); } catch (Exception ex) { LOG.error("Error when writing data to outputstream",ex); }finally { IOTools.close(out); } }finally{ bizlog("/bearer/auth",clientIp,System.currentTimeMillis(), System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } protected String getRealm(HttpServletRequest httpReq) { if (realmMode.equalsIgnoreCase("local")){ return httpClientTool.getContextBase(httpReq) + realm; }else { return realm; } } protected String getBearerToken(HttpServletRequest httpReq, String dft) { String header = httpClientTool.getRequestHeader(httpReq,HEAD_AUTHORIZATION); if (StringUtils.isEmpty(header)){ return dft; } Matcher matcher = bearerPattern.matcher(header); if (matcher.find()){ return matcher.group(1); }else{ return dft; } } protected String getBasicAuth(HttpServletRequest httpReq, String dft) { String header = httpClientTool.getRequestHeader(httpReq,HEAD_AUTHORIZATION); if (StringUtils.isEmpty(header)){ return dft; } Matcher matcher = basicPattern.matcher(header); if (matcher.find()){ return matcher.group(1); }else{ return dft; } } protected void doToken(Logiclet handler,HttpServletRequest httpReq, HttpServletResponse httpResp) { if (handler == null){ throw new BaseException("core.e1000","Handler on-token is not defined"); } String basicAuth = getBasicAuth(httpReq,"0"); Context ctx = new HttpContext(httpReq,httpResp,encoding); LogicletContext logicletContext = new Context.ServantLogicletContext(ctx); long start = System.nanoTime(); String clientIp = httpClientTool.getClientIp(httpReq); try { logicletContext.SetValue("$service", "/bearer/token"); logicletContext.SetValue("$clientIp",clientIp); logicletContext.SetValue("$auth",basicAuth); XsObject doc = new JsonObject("root",new HashMap()); handler.execute(doc,doc, logicletContext, null); int status = PropertiesConstants.getInt(logicletContext,"$status",E200); httpClientTool.setStatus(httpResp,status); OutputStream out = null; try { String data = jsonFactory.toJsonString(doc.getContent()); ctx.setResponseContentType(contentType); out = ctx.getOutputStream(); byte [] bytes = data.getBytes(ctx.getEncoding()); ctx.setResponseContentLength(bytes.length); Context.writeToOutpuStream(out, bytes); out.flush(); } catch (Exception ex) { LOG.error("Error when writing data to outputstream",ex); }finally { IOTools.close(out); } }finally{ bizlog("/bearer/token",clientIp,System.currentTimeMillis(), System.nanoTime() - start,httpReq.getRequestURL().toString(),false,""); } } @Override public void destroy() { } protected String getCommand(String contextPath,String uri){ String prefix = contextPath + this.cmdPrefix; if (uri.startsWith(prefix)){ return uri.substring(prefix.length()); }else{ 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