package com.terra.proxy.servlet; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.terra.proxy.bean.TokenCheckException; import com.terra.proxy.bean.VistorBean; import com.terra.proxy.mapper.ProxyServletMapper; import com.terra.proxy.proxy.SolrProxyServletConfiguration; import com.terra.proxy.util.CrpUtil; import com.terra.proxy.util.HttpContextUtils; import com.terra.proxy.util.JedisUtils; import org.apache.http.*; import org.apache.http.client.utils.URIUtils; import org.apache.http.entity.BasicHttpEntity; import org.mitre.dsmiley.httpproxy.ProxyServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import redis.clients.jedis.Jedis; import javax.annotation.PostConstruct; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URI; import java.util.*; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class SubServlet extends ProxyServlet { private Logger log = LoggerFactory.getLogger(SubServlet.class); @Autowired JedisUtils jedisUtils; @Value("${fromsys}") private String fromsys; ProxyServletMapper service; @PostConstruct public void init() { try { super.init(); } catch (ServletException e) { e.printStackTrace(); } WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); service = wac.getBean(ProxyServletMapper.class); } public static boolean isdigit(String str) { return str.matches("[0-9]+"); } protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { StringBuilder uri = new StringBuilder(1000); String fragment = null; StringBuilder queryString2 = new StringBuilder(1000); if (servletRequest.getPathInfo() != null) {// ex: /my/path.html System.out.println(servletRequest.getPathInfo()); uri.append(encodeUriQuery(servletRequest.getPathInfo())); } URI errorurl = URI.create( "http://" + "localhost" + ":" + servletRequest.getServerPort() + "/404.html"); servletRequest.setAttribute(ATTR_TARGET_HOST, URIUtils.extractHost(errorurl)); String queryString = servletRequest.getQueryString();// ex:(following// // name=value&foo=bar#fragment List serverlist = new ArrayList<>(); Map param = new HashMap(); String code = servletRequest.getPathInfo().split("/")[1]; Integer id = CrpUtil.decode(code); param.put("id", id); param.put("enable", 1); serverlist = service.queryServer(param); param.put("URL", serverlist.get(0).get("URL").toString()); serverlist.add(param); String url = serverlist.get(0).get("URL").toString(); Integer ispublic = Integer.valueOf(serverlist.get(0).get("ISPUBLIC").toString()); VistorBean vb = new VistorBean(servletRequest.getRemoteAddr(), url, id, fromsys); URI hostpath = URI.create(url); servletRequest.setAttribute(ATTR_TARGET_HOST, URIUtils.extractHost(hostpath)); checkToken(queryString, queryString2, ispublic, vb, fragment); if (!url.isEmpty()) { StringBuilder returnuri = new StringBuilder(url); String path = servletRequest.getPathInfo().substring(servletRequest.getPathInfo().indexOf(code.toString()) + code.toString().length() + 1); returnuri.append(path); if (queryString2 != null && queryString2.length() > 0) { if (!(returnuri.indexOf("?") > -1)) { returnuri.append('?'); } returnuri.append(encodeUriQuery(queryString2)); } if (doSendUrlFragment && fragment != null) { returnuri.append('#'); returnuri.append(encodeUriQuery(fragment)); } vb.setResult("success"); visitlogsaveinredis(vb); return returnuri.toString(); } return null; } protected void copyRequestHeaders(HttpServletRequest servletRequest, HttpRequest proxyRequest) { Enumeration enumerationOfHeaderNames = servletRequest.getHeaderNames(); while (enumerationOfHeaderNames.hasMoreElements()) { String headerName = (String) enumerationOfHeaderNames.nextElement(); if ((!headerName.equalsIgnoreCase("Content-Length")) && (!hopByHopHeaders.containsHeader(headerName))) { Enumeration headers = servletRequest.getHeaders(headerName); while (headers.hasMoreElements()) { String headerValue = (String) headers.nextElement(); if (headerName.equalsIgnoreCase("Host")) { HttpHost host = getTargetHost(servletRequest); headerValue = host.getHostName(); if (host.getPort() != -1) { headerValue = headerValue + ":" + host.getPort(); } } else if (headerName.equalsIgnoreCase("Cookie")) { headerValue = getRealCookie(headerValue); } proxyRequest.addHeader(headerName, headerValue); } } } } private HttpHost getTargetHost(HttpServletRequest servletRequest) { return (HttpHost) servletRequest.getAttribute(ATTR_TARGET_HOST); } public static boolean isInteger(String str) { Pattern pattern = Pattern.compile("^[1-9]\\d*|0$"); return pattern.matcher(str).matches(); } /** * 验证token * * @param queryString * @param ispublic * @param vb */ public void checkToken(String queryString, StringBuilder queryString2, Integer ispublic, VistorBean vb, String fragment) { // split off fragment from queryString, updating queryString if found if (queryString != null) { // 针对请求地址的参数做操作 // 判断是否带了token if (queryString.indexOf("token") == -1 && ispublic != 1) { vb.setResult("fail"); visitlogsaveinredis(vb); throw new TokenCheckException("未传入token", "500"); } String par[] = queryString.split("&"); for (int i = 0; i < par.length; i++) { String a = par[i].split("=")[0]; String v = par[i].split("=").length >= 2 ? par[i].split("=")[1] : ""; if ("token".equals(a)) { // 判断内存里有咩有匹配的token,咩有去redis库里查询,库里没有,则在内存和库中存储,库里有,存入内存 if (!SolrProxyServletConfiguration.tokens.contains(v)) { Jedis jedis = null; try { jedis = JedisUtils.getJedis(); if (!jedis.exists(v)) { vb.setResult("fail"); visitlogsaveinredis(vb); throw new TokenCheckException("token不存在", "500"); } } catch (Exception e) { e.printStackTrace(); } finally { jedis.close(); } } } else { queryString2.append("&").append(par[i]); } } int fragIdx = queryString.indexOf('#'); if (fragIdx >= 0) { fragment = queryString.substring(fragIdx + 1); queryString = queryString.substring(0, fragIdx); } } else { if (ispublic != 1) { vb.setResult("fail"); visitlogsaveinredis(vb); throw new TokenCheckException("未传入token", "500"); } } } /** * 统计不同ip调用服务次数,并将其存入入redis * * @param vb 日志bean */ private void visitlogsaveinredis(VistorBean vb) { String fromip = vb.getRequestip(); vb.setDate(new Date()); Jedis jedis = null; int count = 0; try { jedis = JedisUtils.getJedis(); jedis.sadd("visitlog", JSONObject.toJSONStringWithDateFormat(vb, "yyyy-MM-dd HH:mm:ss", SerializerFeature.PrettyFormat)); } catch (Exception e) { // TODO: handle exception log.error("redis包错"); } finally { jedis.close(); } } protected void copyResponseHeaders(HttpResponse proxyResponse, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { for (Header header : proxyResponse.getAllHeaders()) { if (!hopByHopHeaders.containsHeader(header.getName())) { if ((header.getName().equalsIgnoreCase("Set-Cookie")) || (header.getName().equalsIgnoreCase("Set-Cookie2"))) { copyProxyCookie(servletRequest, servletResponse, header); } else { servletResponse.addHeader(header.getName(), header.getValue()); System.out.print(header.getName() + header.getValue()); } } } System.out.print(servletResponse.containsHeader("Content-Length")); } public boolean isgzip(HttpEntity entity) { return entity.getContentEncoding() != null && "Content-Encoding: gzip".equals(entity.getContentEncoding().toString()) ? true : false; } public static byte[] compress(String str) { ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = null; try { gzip = new GZIPOutputStream(out); gzip.write(str.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (gzip != null) { try { gzip.close(); } catch (IOException e) { e.printStackTrace(); } } } return out.toByteArray(); } protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse servletResponse) throws IOException { HttpEntity entity = proxyResponse.getEntity(); BufferedReader reader; InputStream is = entity.getContent(); servletResponse.setCharacterEncoding("UTF-8"); if (isgzip(entity)) { reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(is))); StringBuffer sb = new StringBuffer(); String s = null; while ((s = reader.readLine()) != null) { sb.append(s); } String result = sb.toString(); String repx = "]+>([^<]+)";//a标签过滤 result = result.replaceAll(repx, ""); result = result.replaceAll("(http|https)://[^/]+/", "/"); HttpServletRequest hsr = HttpContextUtils.getHttpServletRequest(); BasicHttpEntity entity2 = new BasicHttpEntity(); byte[] bt; bt = compress(result); ByteArrayInputStream btinput = new ByteArrayInputStream(bt); entity2.setContent(btinput); entity2.setContentEncoding("gzip"); entity2.setContentType(entity.getContentType()); entity2.setChunked(false); if (entity2 != null) { servletResponse.addHeader("Content-Length", String.valueOf(bt.length)); OutputStream servletOutputStream = servletResponse.getOutputStream(); entity2.writeTo(servletOutputStream); } } else { if (entity != null && "application/xml; charset=utf-8".equals(entity.getContentType().getValue())) { reader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String s = null; while ((s = reader.readLine()) != null) { sb.append(s); } String result = sb.toString(); result = result.replaceAll("(http|https)://[^/]+/", "/"); BasicHttpEntity entity2 = new BasicHttpEntity(); byte[] bt; bt = result.getBytes(); ByteArrayInputStream btinput = new ByteArrayInputStream(bt); entity2.setContent(btinput); entity2.setContentType(entity.getContentType()); entity2.setChunked(false); servletResponse.addHeader("Content-Length", String.valueOf(bt.length)); OutputStream servletOutputStream = servletResponse.getOutputStream(); entity2.writeTo(servletOutputStream); } else { if (entity != null) { OutputStream servletOutputStream = servletResponse.getOutputStream(); entity.writeTo(servletOutputStream); } } } } }