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<Map> serverlist = new ArrayList<>();
|
Map<String, Object> 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[^>]+>([^<]+</a>)";//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);
|
}
|
}
|
}
|
}
|
|
}
|