I. Use scenarios
_Generally speaking, we design the front desk and the back desk for ordinary users to access and provide services to ordinary users. Then the back desk is used by system administrators to manage and maintain the data of the front desk and to configure the parameters of some environments. Backstage management is generally only accessible to employees within the company, so we usually restrict it by IP. Visit, to achieve the designated crowd to access the background.
II. Realization Principle
- Configure the IP address allowed to be accessed into the properties file.
- Write a filter, read the properties file that saves the IP whitelist in the init method of the filter, parse the IP address of the configuration, and store it in a List collection.
- In the filter's doFilter() method, get the IP address of the visiting user, and then match the user's IP with the white list IP list in the List collection one by one. Once there is a match, release the request; if they do not match, jump to the denial of access page to prompt the user.
3. Code Implementation
- IP Whitelist Configuration
Usually we need to provide three ways to configure IP whitelist
_1). Configuration of a single IP address, with commas or separated between multiple addresses
_2. Configuration of IP address intervals with commas or separated intervals, such as 192.168.1.0-192.168.1.10; 192.168.1.20-192.168.1.50
Wildcards, many separated by commas or segregated, such as 192.168.0.*
Examples are as follows:
#Configuration of a single IP address, separated by commas or partitions
allowIP=192.168.0.105;192.168.0.108;127.0.0.1
#Configuration of IP address intervals, with commas or separated intervals
allowIPRange=192.168.0.10-192.168.0.20;192.168.0.100-192.168.0.110
#Wildcard characters, separated by commas or separated
allowIPWildcard=192.168.0.*;
- Writing of filters
package com.legendshop.filter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.legendshop.exception.IPAccessException;
import com.legendshop.exception.IPFormatException;
public class IPFilter implements Filter {
//Regular expressions used to store initialized IP whitelist lists
private List<String> allowRegexList = new ArrayList<String>();
@Override
public void init(FilterConfig config) throws ServletException {
try {
//Initialize the whitelist list when the filter is initialized
initAllowList();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initAllowList() throws IOException{
//Read the configuration file and load it into the Properties collection
InputStream inStream = new FileInputStream("ipFilter.properties");
Properties prop = new Properties();
prop.load(inStream);
//Obtaining IP configurations in three different configurations
String allowIP = prop.getProperty("allowIP");
String allowIPRange = prop.getProperty("allowIPRange");
String allowIPWildcard = prop.getProperty("allowIPWildcard");
//Format checking of IP whitelist in three ways of user configuration
if(!validate(allowIP, allowIPRange, allowIPWildcard)){
throw new RuntimeException("IP White List Format Definition Exceptions!");
}
//Resolve the IP address configured in the first way and add it to the set of white lists for storing IP
if(null != allowIP && !allowIP.trim().equals("")){
String[] address = allowIP.split(",|;");
if(null != address && address.length > 0){
for(String ip : address){
allowRegexList.add(ip);
}
}
}
//Resolve the IP address configured in the second way and add it to the set of white lists for storing IP
if(null != allowIPRange && !allowIPRange.trim().equals("")){
String[] addressRanges = allowIPRange.split(",|;");
if(null != addressRanges && addressRanges.length > 0){
for(String addrRange : addressRanges){
String[] addrParts = addrRange.split("-");
if(null != addrParts && addrParts.length >0 && addrParts.length <= 2){
String from = addrParts[0];
String to = addrParts[1];
String prefix = from.substring(0, from.lastIndexOf(".")+1);
int start = Integer.parseInt(from.substring(from.lastIndexOf(".")+1,from.length()));
int end = Integer.parseInt(to.substring(to.lastIndexOf(".")+1,to.length()));
for(int i = start;i <= end;i++){
allowRegexList.add(prefix+i);
}
}else{
throw new RuntimeException("IP List format definition exception!");
}
}
}
}
//Resolve the IP address configured in the third way into regular expressions one by one and add it to the set of white lists where IP is stored. If you don't understand this, you can see the following remarks first.
if(null != allowIPWildcard && !allowIPWildcard.trim().equals("")){
String[] address = allowIPWildcard.split(",|;");
if(null != address && address.length > 0){
for(String addr : address){
if(addr.indexOf("*") != -1){
//Replace *, with a regular expression that matches a single-ended ip address
addr = addr.replaceAll("\\*", "(1\\\\d{1,2}|2[0-4]\\\\d|25[0-5]|\\\\d{1,2})");
addr = addr.replaceAll("\\.", "\\\\.");//Conversion of the meaning of ____________
allowRegexList.add(addr);
}else{
throw new RuntimeException("IP White List Format Definition Exceptions!");
}
}
}
}
}
public boolean validate(String allowIP,String allowIPRange,String allowIPWildcard){
//Rules for matching each segment of an IP address
String regx = "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})";
//Connecting four segments with points is an expression that matches the entire ip address
String ipRegx = regx + "\\." + regx + "\\."+ regx + "\\." + regx;
//Verify that the IP whitelist format configured in the first configuration is correct
Pattern pattern = Pattern.compile("("+ipRegx+")|("+ipRegx+"(,|;))*");
if(!this.validate(allowIP, pattern)){
return false;
}
//Verify that the IP whitelist format configured by the second configuration is correct
pattern = Pattern.compile("("+ipRegx+")\\-("+ipRegx+")|"+ "(("+ipRegx+")\\-("+ipRegx+")(,|;))*");
if(!this.validate(allowIPRange, pattern)){
return false;
}
//Verify that the IP whitelist format configured in the third configuration mode is correct
pattern = Pattern.compile("("+regx+"\\."+ regx+"\\."+regx+"\\."+ "\\*)|"+"("+regx+"\\."+regx+"\\."+regx+"\\."+ "\\*(,|;))*");
if(!this.validate(allowIPWildcard, pattern)){
return false;
}
return true;
}
//Verify that the ip list format of user configuration is correct
public boolean validate(String allowIP,Pattern pattern){
//If it's empty, don't deal with it.
if(null != allowIP && !allowIP.trim().equals("")){
StringBuilder sb = new StringBuilder(allowIP);
//If the user configures more than one IP, but does not end with a semicolon, add a semicolon here.
if(!allowIP.endsWith(";")){
sb.append(";");
}
//If not matched
if(!pattern.matcher(sb).matches()){
return false;
}
}
return true;
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//1. Get the visitor's IP address
String remoteAddr = request.getRemoteAddr();
if(null == remoteAddr || remoteAddr.trim().equals("")){
throw new RuntimeException("IP The address is empty.,access denied!");
}
//If the white list is empty, it is considered that no restrictions have been imposed and released.
if(null == allowRegexList || allowRegexList.size() == 0){
filterChain.doFilter(request, response);
return;
}
//Check whether user IP is on the whitelist
if(checkIp(remoteAddr)){
filterChain.doFilter(request, response);
return;
}else{
throw new RuntimeException("Your IP:"+remoteAddr+",Not on the white list,access denied!");
}
}
//Check whether user IP is on the whitelist
public boolean checkIp(String remoteAddr){
for(String regex : allowRegexList){
if(remoteAddr.matches(regex)){
return true;
}
}
return false;
}
@Override
public void destroy() {
}
}
Three. Remarks
In this paper, it is difficult to understand the parsing of the third way of IP configuration. My program is to parse the white list of IP configuration in the third way into regular expressions, such as 192.168.1. User configuration is 192.168.1. I do not parse it into 256 IP addresses from 192.168.1.0 to 192.168.1.255, and then put it into the List set, but 192.168.1. I parse it into a regular expression 192.168.1. (1 \ D {1, 1.) 2} | 2 [0-4] D 25 [0-5] \ D {1,2} can match 256 IP addresses from 192.168.1.0 to 192.168.1.255, which greatly reduces the number of program cycles and improves the performance of the program. But because I store regularities here, I simply interpret the set of white lists I defined earlier as that every item stored in it is regular and matches white. The rule of the list. Whether it's an IP address, such as 192.168.1.1, I think it's a rule. So here's how I check whether the user's IP is in the white list:
//Check whether user IP is on the whitelist
public boolean checkIp(String remoteAddr){
//Match each item in the whitelist as a rule
for(String regex : allowRegexList){
if(remoteAddr.matches(regex)){
return true;
}
}
return false;
}