Skip to content

Commit 274b387

Browse files
committed
feat: implement #7
1 parent f059642 commit 274b387

13 files changed

Lines changed: 1538 additions & 2 deletions

File tree

Cyaim.WebSocketServer/Cyaim.WebSocketServer.sln

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 18
4-
VisualStudioVersion = 18.0.11217.181 d18.0
4+
VisualStudioVersion = 18.0.11217.181
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cyaim.WebSocketServer", "Cyaim.WebSocketServer\Cyaim.WebSocketServer.csproj", "{F1683A2D-FA48-4F06-B99D-AD9548EF060D}"
77
EndProject
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cyaim.WebSocketServer.Examp
2323
EndProject
2424
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cyaim.WebSocketServer.Sample.Dashboard", "Sample\Cyaim.WebSocketServer.Sample.Dashboard\Cyaim.WebSocketServer.Sample.Dashboard.csproj", "{EA37AAED-D05E-A539-F096-B6520032CFD7}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cyaim.WebSocketServer.Sample.AccessControl", "Sample\Cyaim.WebSocketServer.Sample.AccessControl\Cyaim.WebSocketServer.Sample.AccessControl.csproj", "{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -129,6 +131,18 @@ Global
129131
{EA37AAED-D05E-A539-F096-B6520032CFD7}.Release|x64.Build.0 = Release|Any CPU
130132
{EA37AAED-D05E-A539-F096-B6520032CFD7}.Release|x86.ActiveCfg = Release|Any CPU
131133
{EA37AAED-D05E-A539-F096-B6520032CFD7}.Release|x86.Build.0 = Release|Any CPU
134+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
135+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|Any CPU.Build.0 = Debug|Any CPU
136+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|x64.ActiveCfg = Debug|Any CPU
137+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|x64.Build.0 = Debug|Any CPU
138+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|x86.ActiveCfg = Debug|Any CPU
139+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Debug|x86.Build.0 = Debug|Any CPU
140+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|Any CPU.ActiveCfg = Release|Any CPU
141+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|Any CPU.Build.0 = Release|Any CPU
142+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|x64.ActiveCfg = Release|Any CPU
143+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|x64.Build.0 = Release|Any CPU
144+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|x86.ActiveCfg = Release|Any CPU
145+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61}.Release|x86.Build.0 = Release|Any CPU
132146
EndGlobalSection
133147
GlobalSection(SolutionProperties) = preSolution
134148
HideSolutionNode = FALSE
@@ -137,6 +151,7 @@ Global
137151
{26B4308D-3AC5-DB9D-4FCC-08761FD9E25D} = {8AB54424-C8DA-4B64-B84C-8E696D7939C7}
138152
{1E66F9B8-2F53-49AC-FDE8-159A5AF78846} = {B0CA25E1-04AB-4C66-93B8-21DDF6CC996F}
139153
{EA37AAED-D05E-A539-F096-B6520032CFD7} = {B0CA25E1-04AB-4C66-93B8-21DDF6CC996F}
154+
{F9C82F6A-8725-6A10-C3AF-73406DCD1A61} = {B0CA25E1-04AB-4C66-93B8-21DDF6CC996F}
140155
EndGlobalSection
141156
GlobalSection(ExtensibilityGlobals) = postSolution
142157
SolutionGuid = {5078C553-A1C2-42BD-9F21-BCDE0A70B225}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Configuration;
3+
using System;
4+
5+
namespace Cyaim.WebSocketServer.Infrastructure.AccessControl
6+
{
7+
/// <summary>
8+
/// Extension methods for access control configuration / 访问控制配置扩展方法
9+
/// </summary>
10+
public static class AccessControlExtensions
11+
{
12+
/// <summary>
13+
/// Add access control service / 添加访问控制服务
14+
/// </summary>
15+
/// <param name="services">Service collection / 服务集合</param>
16+
/// <param name="configure">Configuration action / 配置操作</param>
17+
/// <returns>Service collection / 服务集合</returns>
18+
public static IServiceCollection AddAccessControl(
19+
this IServiceCollection services,
20+
Action<AccessControlPolicy> configure = null)
21+
{
22+
var policy = new AccessControlPolicy();
23+
configure?.Invoke(policy);
24+
25+
services.AddSingleton(policy);
26+
services.AddSingleton<AccessControlService>();
27+
28+
return services;
29+
}
30+
31+
/// <summary>
32+
/// Add access control service from configuration / 从配置添加访问控制服务
33+
/// </summary>
34+
/// <param name="services">Service collection / 服务集合</param>
35+
/// <param name="configuration">Configuration / 配置</param>
36+
/// <param name="sectionName">Configuration section name (default: "AccessControlPolicy") / 配置节名称(默认:"AccessControlPolicy")</param>
37+
/// <returns>Service collection / 服务集合</returns>
38+
public static IServiceCollection AddAccessControl(
39+
this IServiceCollection services,
40+
IConfiguration configuration,
41+
string sectionName = "AccessControlPolicy")
42+
{
43+
var policy = new AccessControlPolicy();
44+
configuration.GetSection(sectionName).Bind(policy);
45+
46+
services.AddSingleton(policy);
47+
services.AddSingleton<AccessControlService>();
48+
49+
return services;
50+
}
51+
52+
/// <summary>
53+
/// Register geographic location provider / 注册地理位置提供者
54+
/// </summary>
55+
/// <typeparam name="T">Provider type / 提供者类型</typeparam>
56+
/// <param name="services">Service collection / 服务集合</param>
57+
/// <returns>Service collection / 服务集合</returns>
58+
public static IServiceCollection AddGeoLocationProvider<T>(this IServiceCollection services)
59+
where T : class, IGeoLocationProvider
60+
{
61+
services.AddSingleton<IGeoLocationProvider, T>();
62+
return services;
63+
}
64+
}
65+
}
66+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System.Collections.Generic;
2+
3+
namespace Cyaim.WebSocketServer.Infrastructure.AccessControl
4+
{
5+
/// <summary>
6+
/// Access control policy for IP and geographic location filtering
7+
/// IP 和地理位置访问控制策略
8+
/// </summary>
9+
public class AccessControlPolicy
10+
{
11+
/// <summary>
12+
/// Enable access control / 启用访问控制
13+
/// </summary>
14+
public bool Enabled { get; set; } = false;
15+
16+
/// <summary>
17+
/// IP whitelist / IP 白名单
18+
/// Supports CIDR notation (e.g., "192.168.1.0/24") / 支持 CIDR 表示法(例如:"192.168.1.0/24")
19+
/// </summary>
20+
public List<string> IpWhitelist { get; set; } = new List<string>();
21+
22+
/// <summary>
23+
/// IP blacklist / IP 黑名单
24+
/// Supports CIDR notation (e.g., "10.0.0.0/8") / 支持 CIDR 表示法(例如:"10.0.0.0/8")
25+
/// </summary>
26+
public List<string> IpBlacklist { get; set; } = new List<string>();
27+
28+
/// <summary>
29+
/// Country whitelist (ISO 3166-1 alpha-2 country codes, e.g., "CN", "US") / 国家白名单(ISO 3166-1 alpha-2 国家代码,例如:"CN", "US")
30+
/// </summary>
31+
public List<string> CountryWhitelist { get; set; } = new List<string>();
32+
33+
/// <summary>
34+
/// Country blacklist (ISO 3166-1 alpha-2 country codes) / 国家黑名单(ISO 3166-1 alpha-2 国家代码)
35+
/// </summary>
36+
public List<string> CountryBlacklist { get; set; } = new List<string>();
37+
38+
/// <summary>
39+
/// City whitelist (format: "CountryCode:CityName", e.g., "CN:Beijing", "US:New York") / 城市白名单(格式:"CountryCode:CityName",例如:"CN:Beijing", "US:New York")
40+
/// </summary>
41+
public List<string> CityWhitelist { get; set; } = new List<string>();
42+
43+
/// <summary>
44+
/// City blacklist (format: "CountryCode:CityName") / 城市黑名单(格式:"CountryCode:CityName")
45+
/// </summary>
46+
public List<string> CityBlacklist { get; set; } = new List<string>();
47+
48+
/// <summary>
49+
/// Region whitelist (format: "CountryCode:RegionName", e.g., "CN:Beijing", "US:California") / 地区白名单(格式:"CountryCode:RegionName",例如:"CN:Beijing", "US:California")
50+
/// </summary>
51+
public List<string> RegionWhitelist { get; set; } = new List<string>();
52+
53+
/// <summary>
54+
/// Region blacklist (format: "CountryCode:RegionName") / 地区黑名单(格式:"CountryCode:RegionName")
55+
/// </summary>
56+
public List<string> RegionBlacklist { get; set; } = new List<string>();
57+
58+
/// <summary>
59+
/// Action when access is denied / 拒绝访问时的操作
60+
/// </summary>
61+
public AccessDeniedAction DeniedAction { get; set; } = AccessDeniedAction.CloseConnection;
62+
63+
/// <summary>
64+
/// Custom denial message / 自定义拒绝消息
65+
/// </summary>
66+
public string DenialMessage { get; set; } = "Access denied";
67+
68+
/// <summary>
69+
/// Enable geographic location lookup / 启用地理位置查询
70+
/// </summary>
71+
public bool EnableGeoLocationLookup { get; set; } = true;
72+
73+
/// <summary>
74+
/// Cache geographic location results (in seconds) / 缓存地理位置查询结果(秒)
75+
/// </summary>
76+
public int GeoLocationCacheSeconds { get; set; } = 3600; // 1 hour
77+
}
78+
79+
/// <summary>
80+
/// Action to take when access is denied / 拒绝访问时的操作
81+
/// </summary>
82+
public enum AccessDeniedAction
83+
{
84+
/// <summary>
85+
/// Close connection immediately / 立即关闭连接
86+
/// </summary>
87+
CloseConnection,
88+
89+
/// <summary>
90+
/// Return HTTP 403 Forbidden / 返回 HTTP 403 Forbidden
91+
/// </summary>
92+
ReturnForbidden,
93+
94+
/// <summary>
95+
/// Return HTTP 401 Unauthorized / 返回 HTTP 401 Unauthorized
96+
/// </summary>
97+
ReturnUnauthorized
98+
}
99+
}
100+

0 commit comments

Comments
 (0)