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