Apache Mina 白名单实现方法

Mina自带了一个黑名单过滤器BlacklistFilter,可过滤黑名单列表中的网络连接。用来防止非法的客户端访问。

但在某些应用场景里需要设定白名单,只接收某些指定IP的客户端发来的数据。这就需要实现白名单功能。

我们可以自己实现白名单过滤器,方法很简单只需仿照BlacklistFilter做些修改即可。

我自己写的WhiteFilter,代码如下:

/**
 * Whitelist filter (based on Mina's Blacklist filter).
 */
public class WhitelistFilter extends IoFilterAdapter {

	private final List whitelist = new CopyOnWriteArrayList();

	private final static Logger LOGGER = LoggerFactory.getLogger(WhitelistFilter.class);

	public void setWhitelist(InetAddress[] addresses) {
		if (addresses == null) {
			throw new NullPointerException("addresses");
		}
		whitelist.clear();
		for (InetAddress addr : addresses) {
			allow(addr);
		}
	}

	public void setSubnetWhitelist(Subnet[] subnets) {
		if (subnets == null) {
			throw new NullPointerException("Subnets must not be null");
		}
		whitelist.clear();
		for (Subnet subnet : subnets) {
			allow(subnet);
		}
	}

	public void setWhitelist(Iterable addresses) {
		if (addresses == null) {
			throw new NullPointerException("addresses");
		}

		whitelist.clear();

		for (InetAddress address : addresses) {
			allow(address);
		}
	}

	public void setSubnetWhitelist(Iterable subnets) {
		if (subnets == null) {
			throw new NullPointerException("Subnets must not be null");
		}
		whitelist.clear();
		for (Subnet subnet : subnets) {
			allow(subnet);
		}
	}

	public void allow(InetAddress address) {
		if (address == null) {
			throw new NullPointerException("Adress to block can not be null");
		}

		allow(new Subnet(address, 32));
	}

	public void allow(Subnet subnet) {
		if (subnet == null) {
			throw new NullPointerException("Subnet can not be null");
		}

		whitelist.add(subnet);
	}

	public void disallow(InetAddress address) {
		if (address == null) {
			throw new NullPointerException("Adress to unblock can not be null");
		}

		disallow(new Subnet(address, 32));
	}

	public void disallow(Subnet subnet) {
		if (subnet == null) {
			throw new NullPointerException("Subnet can not be null");
		}
		whitelist.remove(subnet);
	}

	@Override
	public void sessionCreated(NextFilter nextFilter, IoSession session) {
		if (isAllowed(session)) {
			nextFilter.sessionCreated(session);
		} else {
			blockSession(session);
		}
	}

	@Override
	public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
		if (isAllowed(session)) {
			nextFilter.sessionOpened(session);
		} else {
			blockSession(session);
		}
	}

	@Override
	public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
		if (isAllowed(session)) {
			nextFilter.sessionClosed(session);
		} else {
			blockSession(session);
		}
	}

	@Override
	public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
		if (isAllowed(session)) {
			nextFilter.sessionIdle(session, status);
		} else {
			blockSession(session);
		}
	}

	@Override
	public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
		if (isAllowed(session)) {
			nextFilter.messageReceived(session, message);
		} else {
			blockSession(session);
		}
	}

	@Override
	public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
		if (isAllowed(session)) {
			nextFilter.messageSent(session, writeRequest);
		} else {
			blockSession(session);
		}
	}

	private void blockSession(IoSession session) {
		LOGGER.warn("Remote address is not allowed; closing.");
		session.close(true);
	}

	private boolean isAllowed(IoSession session) {
		SocketAddress remoteAddress = session.getRemoteAddress();
		if (remoteAddress instanceof InetSocketAddress) {
			InetAddress address = ((InetSocketAddress) remoteAddress).getAddress();

			// check all subnets
			for (Subnet subnet : whitelist) {
				if (subnet.inSubnet(address)) {
					return true;
				}
			}
		}
		return false;
	}
}

调用时要加入whitelist过滤器

IoAcceptor acceptor = new NioSocketAcceptor();

WhitelistFilter whitelistFilter=new WhitelistFilter();
InetAddress[] address= new InetAddress[1];
address[0]=InetAddress.getByName("192.168.136.123");
whitelistFilter.setWhitelist(address);
acceptor.getFilterChain().addFirst("white",whitelistFilter);

acceptor.getFilterChain().addLast("logger", new LoggingFilter());   
          
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("GBK"))));     
acceptor.setHandler(new ServerHandler());     
          
acceptor.getSessionConfig().setReadBufferSize(2048);     
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);     
             
acceptor.bind(new InetSocketAddress(PORT));     

这样服务端只会从指定的IP接收数据,如果客户端使用其他的IP地址则服务端拒绝连接。

你可能感兴趣的:(Apache Mina 白名单实现方法)