001package top.cenze.utils.http.request; 002 003import cn.hutool.core.collection.CollectionUtil; 004import cn.hutool.core.convert.Convert; 005import cn.hutool.core.util.ObjectUtil; 006import cn.hutool.core.util.StrUtil; 007import com.alibaba.fastjson.JSON; 008import com.alibaba.fastjson.JSONObject; 009import com.netflix.zuul.context.RequestContext; 010import com.netflix.zuul.http.ServletInputStreamWrapper; 011import lombok.SneakyThrows; 012import lombok.extern.slf4j.Slf4j; 013import org.apache.commons.lang3.StringUtils; 014import org.springframework.util.StreamUtils; 015 016import javax.servlet.ServletInputStream; 017import javax.servlet.http.HttpServletRequest; 018import javax.servlet.http.HttpServletRequestWrapper; 019import java.io.IOException; 020import java.io.InputStream; 021import java.net.InetAddress; 022import java.net.UnknownHostException; 023import java.nio.charset.Charset; 024import java.util.Arrays; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029@Slf4j 030public class ZuulUtil { 031 032 // 多次反向代理后会有多个ip值 的分割符 033 private final static String IP_UTILS_FLAG = ","; 034 // 未知IP 035 private final static String UNKNOWN = "unknown"; 036 // 本地 IP 037 private final static String LOCALHOST_IP = "0:0:0:0:0:0:0:1"; 038 private final static String LOCALHOST_IP1 = "127.0.0.1"; 039 040 /** 041 * 获取请求TOKEN 042 * @param ctx 043 * @return 044 */ 045 public static String getToken(RequestContext ctx) { 046 // 请求 047 HttpServletRequest request = ctx.getRequest(); 048 049 String token = request.getHeader("TOKEN"); 050 if (StringUtils.isBlank(token)) { 051 token = getParameter(ctx, "TOKEN"); 052 } 053 054 return token; 055 } 056 057 /** 058 * 获取请求参数 059 * @param ctx 060 * @param name 061 * @return 062 */ 063 @SneakyThrows 064 public static String getParameter(RequestContext ctx, String name) { 065 // 请求 066 HttpServletRequest request = ctx.getRequest(); 067 // 请求方法 068 String method = request.getMethod(); 069 070 // get方法,和post、put方法处理方式不同 071 if ("GET".equals(method)) { 072 // 一定要在获取参数前设置一下编码,防止获取的中文乱码 073 request.setCharacterEncoding("UTF-8"); 074 // 关键步骤,一定要get一下,下面才能取到值requestQueryParams 075 request.getParameterMap(); 076 Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams(); 077 if (requestQueryParams == null) { 078 requestQueryParams = new HashMap<>(); 079 } 080 log.info("getParameter requestQueryParams: {}", JSON.toJSONString(requestQueryParams)); 081 082 // 获取参数的第一个值 083 List<String> lstParam = requestQueryParams.get(name); 084 if (CollectionUtil.isNotEmpty(lstParam)) { 085 return lstParam.get(0); 086 } 087 } 088 // post和put需重写HttpServletRequestWrapper 089 else if ("POST".equals(method) || "PUT".equals(method)) { 090 // 获取请求的输入流 091 InputStream in = request.getInputStream(); 092 String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); 093 // 如果body为空初始化为空json 094 if (StrUtil.isEmpty(body)) { 095 body = "{}"; 096 } 097 log.info("getParameter body: {}", body); 098 // 转化成json 099 JSONObject json = JSONObject.parseObject(body); 100 101 if (ObjectUtil.isNotNull(json) && ObjectUtil.isNotNull(json.get(name))) { 102 return Convert.toStr(json.get(name)); 103 } 104 } 105 106 return null; 107 } 108 109 /** 110 * 添加修改请求参数 111 * @param ctx 112 * @param name 113 * @param value 114 */ 115 @SneakyThrows 116 public static void setParameter(RequestContext ctx, String name, Object value) { 117 Map<String, Object> mapParams = new HashMap<>(); 118 mapParams.put(name, value); 119 120 setParameters(ctx, mapParams); 121 } 122 123 /** 124 * 添加修改请求参数集合 125 * @param ctx 126 * @param mapParams 127 */ 128 @SneakyThrows 129 public static void setParameters(RequestContext ctx, Map<String, Object> mapParams) { 130 // 请求 131 HttpServletRequest request = ctx.getRequest(); 132 // 请求方法 133 String method = request.getMethod(); 134 135 // get方法,和post、put方法处理方式不同 136 if ("GET".equals(method)) { 137 // 一定要在获取参数前设置一下编码,防止获取的中文乱码 138 request.setCharacterEncoding("UTF-8"); 139 // 关键步骤,一定要get一下,下面才能取到值requestQueryParams 140 request.getParameterMap(); 141 Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams(); 142 if (requestQueryParams == null) { 143 requestQueryParams = new HashMap<>(); 144 } 145 log.info("setParameter requestQueryParams: {}", JSON.toJSONString(requestQueryParams)); 146 147 // 添加/修改参数 148 if (CollectionUtil.isNotEmpty(mapParams)) { 149 for (Map.Entry<String, Object> entry : mapParams.entrySet()) { 150 requestQueryParams.put(entry.getKey(), Arrays.asList(Convert.toStr(entry.getValue()))); 151 } 152 153 log.info("setParameter newQueryParams: {}", JSON.toJSONString(requestQueryParams)); 154 ctx.setRequestQueryParams(requestQueryParams); 155 } 156 } 157 // post和put需重写HttpServletRequestWrapper 158 else if ("POST".equals(method) || "PUT".equals(method)) { 159 // 获取请求的输入流 160 InputStream in = request.getInputStream(); 161 String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); 162 // 如果body为空初始化为空json 163 if (StrUtil.isEmpty(body)) { 164 body = "{}"; 165 } 166 log.info("setParameter body: {}", body); 167 // 转化成json 168 JSONObject json = JSONObject.parseObject(body); 169 170 // 添加/修改参数 171 if (CollectionUtil.isNotEmpty(mapParams)) { 172 for (Map.Entry<String, Object> entry : mapParams.entrySet()) { 173 json.put(entry.getKey(), entry.getValue()); 174 } 175 176 String newBody = json.toString(); 177 log.info("setParameter newBody: {}", newBody); 178 final byte[] reqBodyBytes = newBody.getBytes(); 179 180 // 重写上下文的HttpServletRequestWrapper 181 ctx.setRequest(new HttpServletRequestWrapper(request) { 182 @Override 183 public ServletInputStream getInputStream() throws IOException { 184 return new ServletInputStreamWrapper(reqBodyBytes); 185 } 186 187 @Override 188 public int getContentLength() { 189 return reqBodyBytes.length; 190 } 191 192 @Override 193 public long getContentLengthLong() { 194 return reqBodyBytes.length; 195 } 196 }); 197 } 198 } 199 } 200 201 /** 202 * 获取访问者真实ip 203 * @param ctx 204 * @return 205 */ 206 public static String getRemoteIP(RequestContext ctx) { 207 // 获取请求 208 HttpServletRequest request = ctx.getRequest(); 209 210 return getRemoteIP(request); 211 } 212 213 /** 214 * 获取访问者真实ip 215 * @param request 216 * @return 217 */ 218 public static String getRemoteIP(HttpServletRequest request) { 219 String ip = null; 220 try { 221 // 以下两个获取在k8s中,将真实的客户端IP,放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。 222 ip = request.getHeader("X-Original-Forwarded-For"); 223 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 224 ip = request.getHeader("X-Forwarded-For"); 225 } 226 // 获取nginx等代理的ip 227 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 228 ip = request.getHeader("x-forwarded-for"); 229 } 230 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 231 ip = request.getHeader("Proxy-Client-IP"); 232 } 233 if (StrUtil.isEmpty(ip) || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { 234 ip = request.getHeader("WL-Proxy-Client-IP"); 235 } 236 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 237 ip = request.getHeader("HTTP_CLIENT_IP"); 238 } 239 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 240 ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 241 } 242 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 243 ip = request.getHeader("X-Real-IP"); 244 } 245 // 兼容k8s集群获取ip 246 if (StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { 247 ip = request.getRemoteAddr(); 248 if (LOCALHOST_IP1.equalsIgnoreCase(ip) || LOCALHOST_IP.equalsIgnoreCase(ip)) { 249 // 根据网卡取本机配置的IP 250 InetAddress iNet = null; 251 try { 252 iNet = InetAddress.getLocalHost(); 253 } catch (UnknownHostException e) { 254 log.error("getClientIp error: ", e); 255 } 256 ip = iNet.getHostAddress(); 257 } 258 } 259 } catch (Exception e) { 260 log.error("IPUtils ERROR ", e); 261 } 262 263 // 使用代理,则获取第一个IP地址 264 if (StrUtil.isNotEmpty(ip) && ip.indexOf(IP_UTILS_FLAG) > 0) { 265 ip = ip.substring(0, ip.indexOf(IP_UTILS_FLAG)); 266 } 267 268 return ip; 269 } 270 271 /** 272 * 获取访问域名 273 * @param ctx 274 * @return 275 */ 276 public static String getServerName(RequestContext ctx) { 277 // 获取请求 278 HttpServletRequest request = ctx.getRequest(); 279 280 return getServerName(request); 281 } 282 283 /** 284 * 获取访问域名 285 * @param request 286 * @return 287 */ 288 public static String getServerName(HttpServletRequest request) { 289 return request.getServerName(); 290 } 291}