一、说明
1.1 什么是黑白名单
黑名单的含义就是不允许黑名单上的ip地址对当前服务器进行访问。
白名单的含义就是只允许白名单上的ip地址访问当前服务器。
1.2 为什么要设计黑白名单?
因为可以有效杜绝其他人连接。将不正确连接,阻挡在传输层。
那么,按这个思路,让我们使用TouchSocket优雅的实现吧。
二、程序集源码
2.1 源码位置
2.2 说明文档
三、安装
Nuget安装TouchSocket
即可,具体步骤详看链接博客。
四、声明限制访问判断类
用接口实现的好处是,实例可以自由实现,比如使用数据库实现,能够实现持久化限制访问名单。
public interface IAccessRestrictions
{
bool AddWhiteList(string ip);
bool AddBlackList(string ip);
bool RemoveWhiteList(string ip);
bool RemoveBlackList(string ip);
bool ExistsWhiteList(string ip);
bool ExistsBlackList(string ip);
}
public class AccessRestrictions : IAccessRestrictions
{
private readonly List<string> m_whiteListIP = new List<string>();
private readonly List<string> m_blackListIP = new List<string>();
public virtual bool AddBlackList(string ip)
{
if (this.m_blackListIP.Contains(ip))
{
return true;
}
this.m_blackListIP.Add(ip);
return true;
}
public virtual bool AddWhiteList(string ip)
{
if (this.m_whiteListIP.Contains(ip))
{
return true;
}
this.m_whiteListIP.Add(ip);
return true;
}
public virtual bool ExistsBlackList(string ip)
{
//实际上此处也可以用正则表达式
return this.m_blackListIP.Contains(ip);
}
public virtual bool ExistsWhiteList(string ip)
{
//实际上此处也可以用正则表达式
return this.m_whiteListIP.Contains(ip);
}
public virtual bool RemoveBlackList(string ip)
{
return this.m_blackListIP.Remove(ip);
}
public virtual bool RemoveWhiteList(string ip)
{
return this.m_whiteListIP.Remove(ip);
}
}
五、声明插件
使用插件,可以很好的隔离处理逻辑。
public class AccessRestrictionsPlugin : PluginBase, ITcpConnectingPlugin<ITcpClientBase>
{
private readonly IAccessRestrictions accessRestrictions;
public AccessRestrictionsPlugin(IAccessRestrictions accessRestrictions)
{
this.accessRestrictions = accessRestrictions ?? throw new ArgumentNullException(nameof(accessRestrictions));
}
public Task OnTcpConnecting(ITcpClientBase client, ConnectingEventArgs e)
{
if (client.IsClient)
{
//此处判断,如果该插件被添加在客户端,则不工作。
return e.InvokeNext();
}
if (this.accessRestrictions.ExistsWhiteList(client.IP))
{
//如果存在于白名单,直接返回,允许连接
return e.InvokeNext();
}
if (this.accessRestrictions.ExistsBlackList(client.IP))
{
//如果存在于黑名单,不允许连接
e.IsPermitOperation = false;
e.Handled = true;//表示此处已经处理OnConnecting消息,其他插件不再路由投递。
return Task.CompletedTask;
}
return e.InvokeNext();
}
}
六、创建服务器
var service = new TcpService();
service.Received = (client, byteBlock, requestInfo) =>
{
//从客户端收到信息
var mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
client.Logger.Info($"已从{client.Id}接收到信息:{mes}");
};
service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts("tcp://127.0.0.1:7789",7790)//同时监听两个地址
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();//添加一个控制台日志注入(注意:在maui中控制台日志不可用)
//注册访问限制实例,AccessRestrictions可自行实现,例如连接数据库做持久化等。
a.RegisterSingleton<IAccessRestrictions, AccessRestrictions>();
})
.ConfigurePlugins(a =>
{
a.Add<AccessRestrictionsPlugin>();//添加访问限制插件
}))
.Start();//启动
service.Logger.Info("服务器成功启动");
本文示例demo