package com.funinbook.filter;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import com.funinbook.service.IApiService;
import com.funinbook.util.HttpUtils;
/**
* ClassName: ApiFilter</br> Function: Filter内部转发实现</br>
*
* @author zeping.li</br>
* @version 1.0</br>
* @Date 2016-9-22 下午1:49:28</br>
*/
@WebFilter(urlPatterns = { "/app/*" })
public class AppFilter implements Filter
{
/**
* 接口对外发布地址及内部servlet服务地址映射map 用此方式,可以将接口外部地址定义为 REST风格,并隐藏我们服务实际地址 key: 对外发布接口地址最后一个斜线地址(包括斜线)
* val: 内部servlet实际服务地址
*/
private Map<String, String> urlMap = new ConcurrentHashMap<String, String>();
@Override
public void init(FilterConfig arg0) throws ServletException
{
// 用户注册
urlMap.put("/regist", "/regist");
// 用户登录
urlMap.put("/login", "/login");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException
{
// 设置字符集
req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
// 获取http对象
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 封装接收到的参数
Map<String, Object> params = new ConcurrentHashMap<String, Object>();
// 从request中取出所有GET方式传送过来的参数(对于接口来说存在很多安全因素,并且不易被处理)
// params.putAll(request.getParameterMap());
// 请求开始时间(纳秒 = 1ms/1000/1000 )
long l1 = System.nanoTime();
params.put(IApiService.MAP_PARAM_START_TIME, l1);
// 获取请求的ip
params.put(IApiService.MAP_PARAM_IP, getIpAddr(request));
// 放置一个唯一序列号(mongodb objectId格式)
params.put(IApiService.MAP_PARAM_REQ_SERIAL_NO, String.valueOf(new ObjectId()));
// 封装数据
request.setAttribute(IApiService.REQUEST_PARAMS, params);
// 判断接口地址路径
String uri = request.getRequestURI();
// 我们现在定义:项目发布为ROOT项目,所有请求均是/app/开头,后面为具体的接口请求地址
String reqPath = uri.replace("/app", "");
// 获取系统服务地址映射
if (StringUtils.isBlank(urlMap.get(reqPath.replace("/app", "")))) {
// 错误请求地址
response.sendError(404);
return;
}
// 跳转到内部实际服务地址
request.getRequestDispatcher(urlMap.get(reqPath.replace("/app", ""))).forward(request, response);
return;
}
@Override
public void destroy()
{
}
/**
* 获取request对象的IP地址
*
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request)
{
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)
|| ip.equals("127.0.0.1")) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)
|| ip.equals("127.0.0.1")) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)
|| ip.equals("127.0.0.1")) {
ip = request.getRemoteAddr();
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)
|| ip.equals("127.0.0.1")) {
ip = request.getHeader("http_client_ip");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)
|| ip.equals("127.0.0.1")) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = "127.0.0.1";
}
// 判断获取到的ip是不是一个字符串
if (ip.contains(",")) {
// 去除空格,并拆分
ip = ip.replaceAll(" ", "");
String[] ips = ip.split(",");
// 循环每一个进行处理,过滤内网地址
for (String temp : ips) {
long num = HttpUtils.ipToLong(temp);
if (num >= 167772160l && num <= 184549375l) {
// 10.0.0.0 - 10.255.255.255
continue;
} else if (num >= 2886729728l && num <= 2887778303l) {
// 172.16.0.0 - 172.31.255.255
continue;
} else if (num >= 3232235520l && num <= 3232301055l) {
// 192.168.0.0 - 192.168.255.255
continue;
} else if (num == 2130706433l) {
// 127.0.0.1
continue;
}
ip = temp;
break;
}
}
return ip;
}
}