.Net 코어 제한 흐름 의 실현 예시
19616 단어 .NetCore흐름 을 제한 하 다
1.vs2019
2..Net Core 3.1
3.AspNetCoreRateLimit 4.0.1 참조
2.기초 사용
1.설정
Startup 파일 에 다음 과 같이 설정 합 니 다.설정 항목 을 모두 앞 에 놓 습 니 다.
public void ConfigureServices(IServiceCollection services)
{
// appsettings.json ip
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
// appsettings.json ip
services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimiting:IpRateLimitPolicies"));
// appsettings.json
services.Configure<ClientRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
// appsettings.json
services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("IpRateLimiting:ClientRateLimitPolicies"));
//
services.AddInMemoryRateLimiting();
// ( 、 )
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
// clientid ip , ,
//services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ip
// , , ip ,
app.UseIpRateLimiting();
app.UseClientRateLimiting();
}
2.규칙 설정규칙 의 설정 은 두 가지 로 나 뉜 다.IP 를 통 해 흐름 을 제한 하고 클 라 이언 트 를 통 해 흐름 을 제한 하 는 것 이다.모두 프로필 을 통 해 파 라 메 터 를 설정 합 니 다.apptsettings.json 에서 다음 과 같이 설정 합 니 다(다른 프로필 을 설정 할 수도 있 습 니 다).
"IpRateLimiting": {
"EnableEndpointRateLimiting": false,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
//"IpWhitelist": [ "198.0.0.1", "::1/10", "192.168.0.13/24" ],
"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
"QuotaExceededResponse": {
"Content": "{{\"code\":429,\"msg\":\"Visit too frequently, please try again later\",\"data\":null}}",
"ContentType": "application/json;utf-8",
"StatusCode": 429
},
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 2
}
],
"ClientRateLimitPolicies": {
"ClientRules": [
{
"ClientId": "client-id-1",
"Rules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 10
},
{
"Endpoint": "*",
"Period": "15m",
"Limit": 200
}
]
}
]
},
"IpRateLimitPolicies": {
"IpRules": [
{
"Ip": "84.247.85.224",
"Rules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 10
},
{
"Endpoint": "*",
"Period": "15m",
"Limit": 200
}
]
}
]
}
}
각 설정 항목 의 설명 은 다음 과 같 습 니 다.EnableEndpoint Rate Limiting:true 로 설정 하면 점 규칙 이*일 때 GET,POST 등 모든 서술 어 는 각각 제한 횟수 를 가진다.예 를 들 어*:/api/values 클 라 이언 트 가 초당 GET/api/values 5 회 호출 제한 을 설정 하면 초당 5 회 호출 할 수 있 지만 5 회 PUT/api/values 를 호출 할 수 있 습 니 다.
false 로 설정 하면 상기 예 에서 GET,POST 등 공유 요청 횟수 가 제 한 됩 니 다.횟수 제한 설정 을 공유 할 지 여부 입 니 다.이 매개 변 수 를 false 로 설정 할 때 점 만 별표*로 설정 하 는 규칙 이 유효 하고 다른 규칙 은 유효 하지 않 으 며 true 로 설정 할 때 모든 규칙 이 유효 합 니 다.
StackBlocked Requests:false 로 설정 한 경우 거 부 된 요청 은 카운터 에 가입 하지 않 습 니 다.예 를 들 어 1 초 에 세 개의 요청 이 있 으 면 스 트림 제한 규칙 이 각각 1 초 에 한 번,1 분 에 세 번 으로 설정 되 어 있 으 면 거 부 된 두 개의 요청 은 1 분 에 세 번 의 규칙 에 기록 되 지 않 습 니 다.즉,이 인 터 페 이 스 를 두 번 호출 할 수 있 습 니 다.true 로 설정 하면 거 부 된 요청 도 계수 기 를 추가 합 니 다.상기 예 와 같이 1 분 안에 호출 할 수 없습니다.세 번 모두 기록 합 니 다.
RealIpHeader:설정 항목 IP 화이트 리스트 IpWhitelist 와 조합 하여 사용 합 니 다.이 매개 변수 가 정의 하 는 요청 헤더 이름 이 요청 에 존재 하고 이 매개 변수 내용 이 IP 화이트 리스트 의 IP 이면 스 트림 규칙 에 제한 을 받 지 않 습 니 다.
Client IdHeader:설정 항목 클 라 이언 트 화이트 리스트 Client IdHeader 와 조합 하여 사용 합 니 다.이 매개 변수 가 정의 하 는 요청 헤더 이름 이 요청 에 존재 하고 이 매개 변수 내용 이 클 라 이언 트 화이트 리스트 의 이름 이 라면 스 트림 규칙 에 제한 을 받 지 않 습 니 다.
HttpStatusCode:http 요청 스 트림 후 되 돌아 오 는 코드 입 니 다.
IpWhitelist:IP 화이트 리스트,필드 지원 Ip v4 와 v6,예 를 들 어"198.0.0.0.1",":1/10","192.168.0.13/24"등.RealIpHeader 매개 변수 에 맞 춰 사용 할 수 있 고 단독으로 사용 할 수 있 으 며 요청 한 ip 는 이 화이트 리스트 규칙 에 부합 되 며 제한 되 지 않 습 니 다.
Endpoint Whitelist:터미널 화이트 리스트 입 니 다.이 터미널 규칙 에 맞 는 요청 은 스 트림 규칙 의 영향 을 받 지 않 습 니 다.예 를 들 어"get:/api/values"는 GET 가 요청 한 api/values 인터페이스 가 영향 을 받 지 않 음 을 표시 합 니 다.*모든 종류의 요청 을 표시 합 니 다.
Client Whitelist:클 라 이언 트 화이트 리스트,Client IdHeader 파라미터 와 함께 사용 하고 클 라 이언 트 의 이름 을 설정 합 니 다.
QuotaExceed Response:스 트림 제한 후의 반환 값 설정,내용,상태 코드 등 을 되 돌려 줍 니 다.
General Rules:유 니 버 설 규칙 설정 입 니 다.세 개의 매개 변 수 는 Endpoint,Period,Limit 입 니 다.
Endpoint 터미널 형식 은{HTTPVerb}:{PATH},get:/api/values 와 같은 모든 HTTP 동 사 를 별표 로 찾 을 수 있 습 니 다.
Period 기간 형식 은{INT}{PERIODTYPE},다음 기간 유형 중 하 나 를 사용 할 수 있 습 니 다:s,m,h,d,각각 초 분 시 일 입 니 다.
Limit 는{LONG}형식 으로 접근 횟수 를 제한 합 니 다.
Client RateLimit Policies:클 라 이언 트 의 흐름 을 제한 하 는 특수 한 설정 입 니 다.규칙 은 일반적인 규칙 과 같이 설정 되 어 있 습 니 다.클 라 이언 트 IdHeader 에 맞 춰 요청 헤더 에서 사용 해 야 합 니 다.app.UseClient RateLimiting()을 사용 해 야 합 니 다.사용 하지 않 으 면 유효 하지 않 습 니 다.이 매개 변수 이름 은 변경 할 수 있 습 니 다.통용 규칙 과 특수 규칙 은 같은 우선 순위 이다.
Ip RateLimitPolicies:IP 제한 흐름 의 특수 설정 입 니 다.규칙 은 일반적인 규칙 과 같이 설정 되 어 있 습 니 다.RealIpHeader 와 함께 요청 헤더 에서 사용 해 야 합 니 다.app.UseIp RateLimiting()을 사용 해 야 합 니 다.사용 하지 않 으 면 유효 하지 않 습 니 다.이 매개 변수 이름 은 변경 할 수 있 습 니 다.통용 규칙 과 특수 규칙 은 같은 우선 순위 이다.
3.특수 규칙 사용
IP 와 클 라 이언 트 특수 규칙 의 사용 은 Program 파일 의 프로그램 입 구 를 다음 과 같이 개조 하여 각자 의 특수 규칙 을 보 냅 니 다.
public static async Task Main(string[] args)
{
IWebHost webHost = CreateWebHostBuilder(args).Build();
using (var scope = webHost.Services.CreateScope())
{
var clientPolicyStore = scope.ServiceProvider.GetRequiredService<IClientPolicyStore>();
await clientPolicyStore.SeedAsync();
var ipPolicyStore = scope.ServiceProvider.GetRequiredService<IIpPolicyStore>();
await ipPolicyStore.SeedAsync();
}
await webHost.RunAsync();
}
Configure Services 에서 설정 파 라 메 터 를 읽 은 다음 Startup 파일 의 Configure 방법 으로 app.UseIp RateLimiting()또는 app.UseClient RateLimiting()이 IP 특수 규칙 이나 클 라 이언 트 특수 규칙 을 시작 하 는 경우 먼저 실 행 된 것 이 적 용 됩 니 다.3.복귀 요청
스 트림 제한 이 시 작 된 후 스 트림 제한 규칙 을 실행 하 는 리 턴 헤드 에는 세 개의 매개 변수 가 있 습 니 다.
X-Rate-limit-limit:현재 시간,예 를 들 어 1d.
X-Rate-limit-Reamining:요청 가능 횟수 가 남 았 습 니 다.
X-Rate-limit-Reset:다음 요청 횟수 초기 화 시간.
여러 개의 제한 규칙 은 가장 긴 주기의 규칙 으로 표 시 됩 니 다.
설정 파일 에 반환 정 보 를 설정 합 니 다.알림 정 보 를 되 돌려 주 는 것 외 에 제한 규칙 알림 도 되 돌려 줍 니 다.다음 과 같 습 니 다.
"Content": "{{\"code\":429,\"msg\":\" , {1}{0} , {2} \",\"data\":null}}",
{0}현재 저지 규칙 에 규정된 횟수 를 교체 할 수 있 습 니 다.{1}시간 구간 의 단위 s,h 등 을 교체 할 수 있 습 니 다.{2}몇 초 교체 한 후 해당 단 위 를 하늘 이나 시간 등 으로 환산 할 수 있 습 니 다.4.Redis 저장 소 사용
흐름 제한 규칙 등 은 현재 메모리 로 저장 되 어 있 으 며,우 리 는 실제 와 결합 하여 redis 저장 소 를 사용 할 것 입 니 다.Microsoft.Extensions.Cacing.Redis 를 사용 하면 이런 목적 을 달성 할 수 있 습 니 다.
그러나 성능 에 문제 가 있 을 것 같 아서 우리 가 교체 하고 CSRedis 로 포장 하 는 방법 을 사 용 했 지만 여기 서 는 설명 하지 않 았 다.
저 희 는 세 가지 데이터 1,방문 계수 2,ip 특수 규칙 3,클 라 이언 트 특수 규칙 을 캐 시 합 니 다.
1.방문 계수
public class RedisRateLimitCounterStore : IRateLimitCounterStore
{
private readonly ILogger _logger;
private readonly IRateLimitCounterStore _memoryCacheStore;
private readonly RedisCache _redisCache;
public RedisRateLimitCounterStore(
IMemoryCache memoryCache,
ILogger<RedisRateLimitCounterStore> logger)
{
_logger = logger;
_memoryCacheStore = new MemoryCacheRateLimitCounterStore(memoryCache);
_redisCache = new RedisCache();
}
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return await TryRedisCommandAsync(
() =>
{
return _redisCache.KeyExistsAsync(id, 0);
},
() =>
{
return _memoryCacheStore.ExistsAsync(id, cancellationToken);
});
}
public async Task<RateLimitCounter?> GetAsync(string id, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return await TryRedisCommandAsync(
async () =>
{
var value = await _redisCache.GetStringAsync(id, 0);
if (!string.IsNullOrEmpty(value))
{
return JsonConvert.DeserializeObject<RateLimitCounter?>(value);
}
return null;
},
() =>
{
return _memoryCacheStore.GetAsync(id, cancellationToken);
});
}
public async Task RemoveAsync(string id, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
_ = await TryRedisCommandAsync(
async () =>
{
await _redisCache.KeyDeleteAsync(id, 0);
return true;
},
async () =>
{
await _memoryCacheStore.RemoveAsync(id, cancellationToken);
return true;
});
}
public async Task SetAsync(string id, RateLimitCounter? entry, TimeSpan? expirationTime = null, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
_ = await TryRedisCommandAsync(
async () =>
{
var exprie = expirationTime.HasValue ? Convert.ToInt32(expirationTime.Value.TotalSeconds) : -1;
await _redisCache.SetStringAsync(id, JsonConvert.SerializeObject(entry.Value), exprie);
return true;
},
async () =>
{
await _memoryCacheStore.SetAsync(id, entry, expirationTime, cancellationToken);
return true;
});
}
private async Task<T> TryRedisCommandAsync<T>(Func<Task<T>> command, Func<Task<T>> fallbackCommand)
{
if (_redisCache != null)
{
try
{
return await command();
}
catch (Exception ex)
{
_logger.LogError($"Redis command failed: {ex}");
}
}
return await fallbackCommand();
}
}
2.ip 특수 규칙
public class RedisIpPolicyStore : IIpPolicyStore
{
private readonly IpRateLimitOptions _options;
private readonly IpRateLimitPolicies _policies;
private readonly RedisCache _redisCache;
public RedisIpPolicyStore(
IOptions<IpRateLimitOptions> options = null,
IOptions<IpRateLimitPolicies> policies = null)
{
_options = options?.Value;
_policies = policies?.Value;
_redisCache = new RedisCache();
}
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
{
return await _redisCache.KeyExistsAsync($"{_options.IpPolicyPrefix}", 0);
}
public async Task<IpRateLimitPolicies> GetAsync(string id, CancellationToken cancellationToken = default)
{
string stored = await _redisCache.GetStringAsync($"{_options.IpPolicyPrefix}", 0);
if (!string.IsNullOrEmpty(stored))
{
return JsonConvert.DeserializeObject<IpRateLimitPolicies>(stored);
}
return default;
}
public async Task RemoveAsync(string id, CancellationToken cancellationToken = default)
{
await _redisCache.DelStringAsync($"{_options.IpPolicyPrefix}", 0);
}
public async Task SeedAsync()
{
// on startup, save the IP rules defined in appsettings
if (_options != null && _policies != null)
{
await _redisCache.SetStringAsync($"{_options.IpPolicyPrefix}", JsonConvert.SerializeObject(_policies), 0).ConfigureAwait(false);
}
}
public async Task SetAsync(string id, IpRateLimitPolicies entry, TimeSpan? expirationTime = null, CancellationToken cancellationToken = default)
{
var exprie = expirationTime.HasValue ? Convert.ToInt32(expirationTime.Value.TotalSeconds) : -1;
await _redisCache.SetStringAsync($"{_options.IpPolicyPrefix}", JsonConvert.SerializeObject(_policies), 0, exprie);
}
}
3.클 라 이언 트 특수 규칙
public class RedisClientPolicyStore : IClientPolicyStore
{
private readonly ClientRateLimitOptions _options;
private readonly ClientRateLimitPolicies _policies;
private readonly RedisCache _redisCache;
public RedisClientPolicyStore(
IOptions<ClientRateLimitOptions> options = null,
IOptions<ClientRateLimitPolicies> policies = null)
{
_options = options?.Value;
_policies = policies?.Value;
_redisCache = new RedisCache();
}
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
{
return await _redisCache.KeyExistsAsync($"{_options.ClientPolicyPrefix}", 0);
}
public async Task<ClientRateLimitPolicy> GetAsync(string id, CancellationToken cancellationToken = default)
{
string stored = await _redisCache.GetStringAsync($"{_options.ClientPolicyPrefix}", 0);
if (!string.IsNullOrEmpty(stored))
{
return JsonConvert.DeserializeObject<ClientRateLimitPolicy>(stored);
}
return default;
}
public async Task RemoveAsync(string id, CancellationToken cancellationToken = default)
{
await _redisCache.DelStringAsync($"{_options.ClientPolicyPrefix}", 0);
}
public async Task SeedAsync()
{
// on startup, save the IP rules defined in appsettings
if (_options != null && _policies != null)
{
await _redisCache.SetStringAsync($"{_options.ClientPolicyPrefix}", JsonConvert.SerializeObject(_policies), 0).ConfigureAwait(false);
}
}
public async Task SetAsync(string id, ClientRateLimitPolicy entry, TimeSpan? expirationTime = null, CancellationToken cancellationToken = default)
{
var exprie = expirationTime.HasValue ? Convert.ToInt32(expirationTime.Value.TotalSeconds) : -1;
await _redisCache.SetStringAsync($"{_options.ClientPolicyPrefix}", JsonConvert.SerializeObject(_policies), 0, exprie);
}
}
이후 Startup 파일 에 대응 하 는 주입 을 추가 합 니 다.
services.AddSingleton<IRateLimitCounterStore, RedisRateLimitCounterStore>();
services.AddSingleton<IIpPolicyStore, RedisIpPolicyStore>();
services.AddSingleton<IClientPolicyStore, RedisClientPolicyStore>();
그리고 실행 하면 redis 에서 볼 수 있어 요.5.규칙 수정
규칙 은 IP 와 클 라 이언 트 의 특수 한 규칙 만 수정 할 수 있 습 니 다.이전 부분 에 규칙 을 바 꾸 는 대응 redis 추가 삭제 검사 기능 이 주입 되 었 기 때문에 우 리 는 이런 방법 으로 규칙 을 다시 쓸 수 있 습 니 다.다음 과 같 습 니 다.
public class ClientRateLimitController : Controller
{
private readonly ClientRateLimitOptions _options;
private readonly IClientPolicyStore _clientPolicyStore;
public ClientRateLimitController(IOptions<ClientRateLimitOptions> optionsAccessor, IClientPolicyStore clientPolicyStore)
{
_options = optionsAccessor.Value;
_clientPolicyStore = clientPolicyStore;
}
[HttpGet]
public ClientRateLimitPolicy Get()
{
return _clientPolicyStore.Get($"{_options.ClientPolicyPrefix}_cl-key-1");
}
[HttpPost]
public void Post()
{
var id = $"{_options.ClientPolicyPrefix}_cl-key-1";
var clPolicy = _clientPolicyStore.Get(id);
clPolicy.Rules.Add(new RateLimitRule
{
Endpoint = "*/api/testpolicyupdate",
Period = "1h",
Limit = 100
});
_clientPolicyStore.Set(id, clPolicy);
}
}
여기 서'Net Core 제한 흐름 의 실현 예시'에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 내용 을 소개 합 니 다.Net Core 제한 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
NPOI Excel 여러 개를 하나의 Excel로 결합구현 코드 Nuget에서 NPOI 검색 및 설치 NPOI를 사용하여 참조를 추가합니다.HSSF.UserModel;...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.