C# 实现为Tcp服务器设计访问黑名单、白名单
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
一、说明
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
{
readonly List<string> whiteListIP = new List<string>();
readonly List<string> blackListIP = new List<string>();
public virtual bool AddBlackList(string ip)
{
if (blackListIP.Contains(ip))
{
return true;
}
blackListIP.Add(ip);
return true;
}
public virtual bool AddWhiteList(string ip)
{
if (whiteListIP.Contains(ip))
{
return true;
}
whiteListIP.Add(ip);
return true;
}
public virtual bool ExistsBlackList(string ip)
{
//实际上此处也可以用正则表达式
return this.blackListIP.Contains(ip);
}
public virtual bool ExistsWhiteList(string ip)
{
//实际上此处也可以用正则表达式
return this.whiteListIP.Contains(ip);
}
public virtual bool RemoveBlackList(string ip)
{
return this.blackListIP.Remove(ip);
}
public virtual bool RemoveWhiteList(string ip)
{
return this.whiteListIP.Remove(ip);
}
}
五、声明插件
使用插件可以很好的隔离处理逻辑。
public class AccessRestrictionsPlugin : TcpPluginBase
{
private readonly IAccessRestrictions accessRestrictions;
public AccessRestrictionsPlugin(IAccessRestrictions accessRestrictions)
{
this.accessRestrictions = accessRestrictions ?? throw new ArgumentNullException(nameof(accessRestrictions));
}
protected override void OnConnecting(ITcpClientBase client, ClientOperationEventArgs e)
{
if (client is ITcpClient)
{
//此处判断如果该插件被添加在客户端则不工作。
return;
}
if (this.accessRestrictions.ExistsWhiteList(client.IP))
{
//如果存在于白名单直接返回允许连接
return;
}
if (this.accessRestrictions.ExistsBlackList(client.IP))
{
//如果存在于黑名单不允许连接
e.IsPermitOperation = false;
e.Handled = true;//表示此处已经处理OnConnecting消息其他插件不再路由投递。
return;
}
base.OnConnecting(client, e);
}
}
六、创建服务器
static void Main(string[] args)
{
TcpService service = new TcpService();
service.Received = (client, byteBlock, requestInfo) =>
{
//从客户端收到信息
string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
client.Logger.Info($"已从{client.ID}接收到信息{mes}");
};
service.Setup(new TouchSocketConfig()//载入配置
.UsePlugin()
.SetListenIPHosts(new IPHost[] { new IPHost("tcp://127.0.0.1:7789"), new IPHost(7790) })//同时监听两个地址
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();//添加一个控制台日志注入注意在maui中控制台日志不可用
a.RegisterSingleton<IAccessRestrictions, AccessRestrictions>();//注册访问限制实例AccessRestrictions可自行实现例如连接数据库做持久化等。
})
.ConfigurePlugins(a =>
{
a.Add<AccessRestrictionsPlugin>();//添加访问限制插件
}))
.Start();//启动
service.Logger.Info("服务器成功启动");
Console.ReadKey();
}
本文示例demo