SpringMVC通過(guò)攔截器實(shí)現(xiàn)IP黑名單
本文實(shí)例為大家分享了SpringMVC通過(guò)攔截器實(shí)現(xiàn)IP黑名單的具體代碼,供大家參考,具體內(nèi)容如下
以前沒(méi)有遇到這個(gè)需要,后面在網(wǎng)上找了很久,參考了很多文檔給出的方案。
1.配置攔截器
這里使用全局?jǐn)r截:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.nps.base.filter.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
攔截器LoginInterceptor代碼:
package com.nps.base.filter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.nps.utils.IpInterceptUtils;
/**
* 驗(yàn)證攔截器
* @author HUANG
*/
public class LoginInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory
.getLogger(LoginInterceptor.class);
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String ip = getIpAddress(request);
if (IpInterceptUtils.chickIpBreak(ip)) {
return false;
}
Map<String, String> map = getParameterMap(request);// 獲取url中的所有參數(shù)
String servletUrl = request.getServletPath();// servlet地址
String url = getRealUrl(servletUrl, map);
if (url.indexOf("/user/") == 0) {
Object user = request.getSession().getAttribute("User");
if (user == null) {
// System.out.println("尚未登錄,調(diào)到登錄頁(yè)面");
response.sendRedirect(request.getContextPath() + "/loginOut.do");
return false;
}
}
return true;
}
/**
* 獲取請(qǐng)求主機(jī)IP地址,如果通過(guò)代理進(jìn)來(lái),則透過(guò)防火墻獲取真實(shí)IP地址;
*
* @param request
* @return
* @throws IOException
*/
public final static String getIpAddress(HttpServletRequest request)
throws IOException {
// 獲取請(qǐng)求主機(jī)IP地址,如果通過(guò)代理進(jìn)來(lái),則透過(guò)防火墻獲取真實(shí)IP地址
String ip = request.getHeader("X-Forwarded-For");
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip="
// + ip);
// }
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip="
// + ip);
// }
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip="
// + ip);
// }
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip="
// + ip);
// }
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip="
// + ip);
// }
}
if (ip == null || ip.length() == 0
|| "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
// if (logger.isInfoEnabled()) {
// logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip="
// + ip);
// }
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
}
/**
* 根據(jù)request獲取所有的參數(shù)集
*
* @param request
* @return
*/
protected Map<String, String> getParameterMap(HttpServletRequest request) {
Enumeration<String> names = request.getParameterNames();
String name;
Map<String, String> map = new HashMap<String, String>();
while (names.hasMoreElements()) {
name = names.nextElement();
map.put(name, request.getParameter(name).trim().replaceAll("'", ""));
}
return map;
}
/**
* 獲取url
*
* @param uri
* @param params
* @return
*/
String getRealUrl(String uri, Map<String, String> params) {
StringBuffer sb = new StringBuffer(uri);
if (params != null) {
int i = 0;
for (String key : params.keySet()) {
i++;
if (i == 1) {
sb.append("?" + key + "=" + params.get(key));
} else {
sb.append("&" + key + "=" + params.get(key));
}
}
}
return sb.toString();
}
}
2.校驗(yàn)IP工具
public class IpInterceptUtils {
private static String date ;
private static PropertiesUtil p=null;
/***
* 校驗(yàn)IP是否加入黑名單
* @param ip
* @return true 是在黑名單
* @throws IOException
*/
public static boolean chickIpBreak(String ip) throws IOException{
if(p == null){
p = new PropertiesUtil("conf/ip-black.properties");
}else{
String str = new SimpleDateFormat("MMddHHmmss").format(new Date());
str=str.substring(0,9);
if(date==null || !date.equals(str)){
date = str;
p = new PropertiesUtil("conf/ip-black.properties");
}
}
Enumeration en = p.getProps().propertyNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
if(key.equals(ip)){
return true;
}
}
return false;
}
}
3.配置文件讀取類
PropertiesUtil
package com.nps.base.model;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.springframework.stereotype.Component;
/**
* 讀取Properties綜合類,默認(rèn)綁定到classpath下的config.properties文件。
* @author
*/
@Component("PropertiesUtil")
public class PropertiesUtil {
//配置文件的路徑
private String configPath=null;
/**
* 配置文件對(duì)象
*/
private Properties props=null;
/**
* 默認(rèn)構(gòu)造函數(shù),用于sh運(yùn)行,自動(dòng)找到classpath下的config.properties。
*/
public PropertiesUtil() throws IOException{
if(props==null){
InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream("conf/application.properties");
props = new Properties();
props.load(in);
//關(guān)閉資源
in.close();
}
}
/**
* 默認(rèn)構(gòu)造函數(shù),用于sh運(yùn)行,自動(dòng)找到classpath下的config.properties。
*/
public PropertiesUtil(String path) throws IOException{
if(props==null){
InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(path);
props = new Properties();
props.load(in);
//關(guān)閉資源
in.close();
}
}
/**
* 根據(jù)key值讀取配置的值
* Jun 26, 2010 9:15:43 PM
* @author 朱志杰
* @param key key值
* @return key 鍵對(duì)應(yīng)的值
* @throws IOException
*/
public String readValue(String key) throws IOException {
return props.getProperty(key);
}
/**
* 讀取properties的全部信息
* @throws FileNotFoundException 配置文件沒(méi)有找到
* @throws IOException 關(guān)閉資源文件,或者加載配置文件錯(cuò)誤
*
*/
public Map<String,String> readAllProperties() throws FileNotFoundException,IOException {
//保存所有的鍵值
Map<String,String> map=new HashMap<String,String>();
Enumeration en = props.propertyNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String Property = props.getProperty(key);
map.put(key, Property);
}
return map;
}
/**
* 設(shè)置某個(gè)key的值,并保存至文件。
* @param key key值
* @return key 鍵對(duì)應(yīng)的值
* @throws IOException
*/
public void setValue(String key,String value) throws IOException {
Properties prop = new Properties();
InputStream fis = new FileInputStream(this.configPath);
// 從輸入流中讀取屬性列表(鍵和元素對(duì))
prop.load(fis);
// 調(diào)用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
// 強(qiáng)制要求為屬性的鍵和值使用字符串。返回值是 Hashtable 調(diào)用 put 的結(jié)果。
OutputStream fos = new FileOutputStream(this.configPath);
prop.setProperty(key, value);
// 以適合使用 load 方法加載到 Properties 表中的格式,
// 將此 Properties 表中的屬性列表(鍵和元素對(duì))寫入輸出流
prop.store(fos,"last update");
//關(guān)閉文件
fis.close();
fos.close();
}
/**
* @return the props
*/
public Properties getProps() {
return props;
}
public static void main(String[] args) {
PropertiesUtil p;
try {
p = new PropertiesUtil("conf/ip-black.properties");
Enumeration en = p.props.propertyNames();
String str="";
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
System.out.println(key);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
附上黑名單IP文件格式
ip-black.properties 配置文件
45.119.99.35
103.253.2.165
157.65.166.51
202.57.55.242
119.82.252.122
140.227.53.126
140.227.211.20
140.227.208.20
116.253.84.183
附加
之所以使用配置文件讀取黑名單IP是為了加快數(shù)據(jù)讀取速度,因?yàn)槊看卧L問(wèn)服務(wù)器都會(huì)被校驗(yàn),使用數(shù)據(jù)庫(kù)會(huì)加大數(shù)據(jù)庫(kù)的壓力,這個(gè)方法中每10秒就會(huì)重新讀取配置文件緩存其實(shí)更好,不使用緩存主要是為了,因?yàn)榉旁诰彺嬷羞€要寫對(duì)應(yīng)的操作方法,如果有什么更好的方法歡迎大家討論。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springcloud-gateway集成knife4j的示例詳解
這篇文章主要介紹了springcloud-gateway集成knife4j的示例詳解,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Spring Boot實(shí)現(xiàn)郵件服務(wù)(附:常見郵箱的配置)
這篇文章主要給大家介紹了關(guān)于Spring Boot實(shí)現(xiàn)郵件服務(wù)的相關(guān)資料,文中還附上了常見郵箱的配置,通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
Spring Batch讀取txt文件并寫入數(shù)據(jù)庫(kù)的方法教程
這篇文章主要給大家介紹了Spring Batch讀取txt文件并寫入數(shù)據(jù)庫(kù)的方法,SpringBatch 是一個(gè)輕量級(jí)、全面的批處理框架。這里我們用它來(lái)實(shí)現(xiàn)文件的讀取并將讀取的結(jié)果作處理,處理之后再寫入數(shù)據(jù)庫(kù)中的功能。需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-04-04
java 單例的五種實(shí)現(xiàn)方式及其性能分析
這篇文章主要介紹了java 單例的五種實(shí)現(xiàn)方式及其性能分析。的相關(guān)資料,需要的朋友可以參考下2017-07-07
Java多線程并發(fā)編程 Synchronized關(guān)鍵字
現(xiàn)有一成員變量 Test,當(dāng)線程 A 調(diào)用 Test 的 synchronized 方法,線程 A 獲得 Test 的同步鎖,同時(shí),線程 B 也去調(diào)用 Test 的 synchronized 方法,此時(shí)線程 B 無(wú)法獲得 Test 的同步鎖,必須等待線程 A 釋放 Test 的同步鎖才能獲得從而執(zhí)行對(duì)應(yīng)方法的代碼2017-05-05
使用Mybatis-plus實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表的內(nèi)部字段進(jìn)行比較
這篇文章主要介紹了使用Mybatis-plus實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表的內(nèi)部字段進(jìn)行比較方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java編程在ICPC快速IO實(shí)現(xiàn)源碼
這篇文章主要介紹了Java Fast IO in ICPC實(shí)現(xiàn)源碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-09-09

