面试题答案
一键面试防止重放攻击的实现思路
- 使用时间戳:在请求中添加时间戳,服务器验证时间戳是否在合理时间范围内。若超出范围,认定为可能的重放攻击。
- 使用随机数(Nonce):每次请求生成唯一随机数,服务器记录已使用的随机数,若再次接收到相同随机数,判定为重放攻击。
- 结合签名:对请求数据(包括时间戳或随机数)进行签名,服务器通过验证签名来确保请求未被篡改。
代码示例
- 使用时间戳
public class TimestampMiddleware
{
private readonly RequestDelegate _next;
private const int MaxTimeDifferenceInSeconds = 300; // 5分钟
public TimestampMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.TryGetValue("Timestamp", out var timestampHeader))
{
if (long.TryParse(timestampHeader, out var timestamp))
{
var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (Math.Abs(currentTime - timestamp) > MaxTimeDifferenceInSeconds)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Invalid timestamp, possible replay attack.");
return;
}
}
else
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Invalid timestamp format.");
return;
}
}
else
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Timestamp header is missing.");
return;
}
await _next(context);
}
}
在 Startup.cs
中注册中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<TimestampMiddleware>();
// 其他配置
}
- 使用随机数(Nonce)
private static HashSet<string> usedNonces = new HashSet<string>();
public class NonceMiddleware
{
private readonly RequestDelegate _next;
public NonceMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.TryGetValue("Nonce", out var nonceHeader))
{
if (usedNonces.Contains(nonceHeader))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Duplicate nonce, possible replay attack.");
return;
}
else
{
usedNonces.Add(nonceHeader);
}
}
else
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Nonce header is missing.");
return;
}
await _next(context);
}
}
在 Startup.cs
中注册中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<NonceMiddleware>();
// 其他配置
}
- 结合签名
private const string SecretKey = "your_secret_key";
public class SignatureMiddleware
{
private readonly RequestDelegate _next;
public SignatureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers.TryGetValue("Signature", out var signatureHeader) &&
context.Request.Headers.TryGetValue("Data", out var dataHeader) &&
context.Request.Headers.TryGetValue("Timestamp", out var timestampHeader))
{
var expectedSignature = ComputeHMACSHA256(dataHeader + timestampHeader, SecretKey);
if (!signatureHeader.Equals(expectedSignature))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Invalid signature, possible replay or tampered request.");
return;
}
}
else
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Signature, data or timestamp header is missing.");
return;
}
await _next(context);
}
private string ComputeHMACSHA256(string data, string key)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant();
}
}
}
在 Startup.cs
中注册中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<SignatureMiddleware>();
// 其他配置
}
重放攻击对数据安全的威胁
- 数据泄露:攻击者重放包含敏感信息(如登录凭证、交易信息等)的请求,获取用户数据或未授权访问系统资源。
- 数据篡改:重放修改后的请求,导致数据被错误修改,影响业务逻辑的正常执行,例如重复转账操作等。
- 身份伪造:通过重放身份验证请求,攻击者可以冒充合法用户身份,绕过身份验证机制,执行各种操作,破坏系统安全和数据完整性。