在MV中
private async Task<string> ReadPostDataAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
string postData = "";
var requestStream = await actionContext.Request.Content.ReadAsStreamAsync();
byte[] bytes = new byte[requestStream.Length];
requestStream.Read(bytes, 0, bytes.Length);
//设置当前流的位置为流的开始
requestStream.Seek(0, SeekOrigin.Begin);
//将bytes转换为流(生成新的Stream,防止读取一次就被清空数据了)
Stream newStream = new MemoryStream(bytes);
using (newStream)
{
if (newStream.Length > 0)
{
var byts = new byte[newStream.Length];
newStream.Read(byts, 0, (int)byts.Length);
postData = Encoding.UTF8.GetString(byts);
}
}
return postData;
}
在.NET6中
context.HttpContext.Request.EnableBuffering();
string bodyStr = string.Empty;
request.EnableBuffering();//允许多次读取HTTP请求的正文
using (var reader = new StreamReader(request.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false,
leaveOpen: true)
)
{
bodyStr = await reader.ReadToEndAsync();
request.Body.Position = 0;
}
string secretpost = apisecret + timestamp.ToString() + bodyStr;
最后附上MVC和.NET6,WEBAPI加密全部代码
MVC
public class BasicWebApiAuthorize : AuthorizeAttribute
{
/// <summary>
/// 接口加密签名
/// </summary>
public string SecretKey = "XXXXXXXXXXXXX";
public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
try
{
var headers = actionContext.Request.Headers;
if (!TryGetHeaderValue(headers, "timestamp", out string timestamp)
|| !TryGetHeaderValue(headers, "sign", out string sign))
{
await HandleInvalidRequestAsync(actionContext, "请求Header参数无效", cancellationToken);
return;
}
if (!ValidateTimestamp(timestamp))
{
await HandleInvalidRequestAsync(actionContext, "时间戳无效", cancellationToken);
return;
}
string postData = await ReadPostDataAsync(actionContext, cancellationToken);
if (string.IsNullOrEmpty(postData))
{
await HandleInvalidRequestAsync(actionContext, "请求参数为空", cancellationToken);
return;
}
if (!ValidateSign(postData, timestamp, sign))
{
await HandleInvalidRequestAsync(actionContext, "签名无效", cancellationToken);
return;
}
if (!IsUnderAttack(postData))
{
await LogAndSendWorkWxMsg(actionContext, $"存在被攻击内容({postData})");
await HandleInvalidRequestAsync(actionContext, "内容无效", cancellationToken);
return;
}
}
catch (Exception ex)
{
LoggerHelper.Error("授权验证过程中出现错误", ex);
await HandleServerErrorAsync(actionContext, cancellationToken);
}
}
private async Task<string> ReadPostDataAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
string postData = "";
var requestStream = await actionContext.Request.Content.ReadAsStreamAsync();
byte[] bytes = new byte[requestStream.Length];
requestStream.Read(bytes, 0, bytes.Length);
//设置当前流的位置为流的开始
requestStream.Seek(0, SeekOrigin.Begin);
//将bytes转换为流(生成新的Stream,防止读取一次就被清空数据了)
Stream newStream = new MemoryStream(bytes);
using (newStream)
{
if (newStream.Length > 0)
{
var byts = new byte[newStream.Length];
newStream.Read(byts, 0, (int)byts.Length);
postData = Encoding.UTF8.GetString(byts);
}
}
return postData;
}
private async Task HandleInvalidRequestAsync(HttpActionContext actionContext, string errorMessage, CancellationToken cancellationToken)
{
await LogAndSendWorkWxMsg(actionContext, errorMessage);
actionContext.Response = await Task.Run(() => getResultContent(400, errorMessage), cancellationToken);
}
private bool TryGetHeaderValue(HttpRequestHeaders headers, string key, out string value)
{
IEnumerable<string> values;
if (headers.TryGetValues(key, out values) && values.Any())
{
value = values.First();
return true;
}
value = null;
return false;
}
private bool ValidateTimestamp(string timestamp)
{
//验证时间戳是否合法
var timeDate = TimeConvertor.ConvertIntDatetime(Convert.ToDouble(timestamp));
var diffNow = (DateTime.Now - timeDate).TotalMilliseconds;
if (diffNow < -60000 || diffNow > 60000)//6秒内有效
{
return false;
}
// 时间戳验证逻辑...
return true; // 填充实际的验证逻辑
}
private bool ValidateSign(string postData, string timestamp, string sign)
{
// 签名验证逻辑...
//验证签名是否有效
var _sign = StringHelper.EncryptToMD5Lowercase32($"{postData}{timestamp}{SecretKey}");
if (_sign.ToLower() != sign.ToLower())
{
return false;
}
return true; // 填充实际的验证逻辑
}
private bool IsUnderAttack(string postData)
{
// SQL注入检查逻辑...
if (postData.ToLower().Contains("select ") || postData.ToLower().Contains("update ") ||
postData.ToLower().Contains("delete ") || postData.ToLower().Contains("drop "))
{
return false;
}
return true; // 填充实际的检查逻辑
}
private async Task LogAndSendWorkWxMsg(HttpActionContext actionContext, string errorMessage)
{
StringBuilder log = new StringBuilder();
log.AppendLine("接口请求失败:" + errorMessage);
log.AppendLine($"接口名:{actionContext.Request.RequestUri}");
LoggerHelper.Error(log.ToString());
}
private async Task HandleServerErrorAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
actionContext.Response = await Task.Run(() => getResultContent(500, "服务器内部错误"), cancellationToken);
}
private HttpResponseMessage getResultContent(int error_code = 0, string message = "ok")
{
var actionResult = new HttpResponseMessage();
var result = new
{
error_code = error_code,
message = message
};
actionResult.Content = new StringContent(JsonConvert.SerializeObject(result), Encoding.GetEncoding("UTF-8"), "application/json");
return actionResult;
}
}
.NET6中
public class OpenApiHashaFilter : Attribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
//发起请求的时间戳 单位(秒)
string timestamp = GetHeaderValue(request.Headers, "timestamp");
//Md5加密后的字符串
string signature = GetHeaderValue(request.Headers, "signature");
if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(signature))
{
await HandleUnauthorized(context, "请求缺少重要的header信息");
return;
}
if (!DateTime.TryParse(timestamp, out DateTime parsedTimestamp))
{
await HandleUnauthorized(context, "时间戳格式不正确");
return;
}
if (!IsTimestampValid(parsedTimestamp))
{
await HandleUnauthorized(context, "接口请求时间超过规定时间");
return;
}
bool isValidSignature = await ValidateRequestAsync(request, timestamp, signature);
if (!isValidSignature)
{
await HandleUnauthorized(context, "接口请求失败,签名错误,无法请求接口");
return;
}
}
private async Task<bool> ValidateRequestAsync(HttpRequest request, string timestamp, string signature)
{
string apisecret = AppSettingHelper.ReadAppSettings("Open", "hmac_secret");
string data = string.Empty;
if (request.Method == HttpMethods.Get)
{
data = request.GetEncodedUrl();
}
else
{
request.EnableBuffering();
using (var reader = new StreamReader(request.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false,
leaveOpen: true))
{
data = await reader.ReadToEndAsync();
request.Body.Position = 0;
}
}
return ValidateSignature(timestamp, signature, apisecret, data);
}
private static string GetHeaderValue(IHeaderDictionary headers, string key)
{
if (headers.TryGetValue(key, out var values) && values.Any())
{
return HttpUtility.UrlDecode(values.FirstOrDefault());
}
return null;
}
private async Task HandleUnauthorized(AuthorizationFilterContext context, string errorMessage)
{
context.Result = new ObjectResult(new { error = "Unauthorized", errorMessage })
{
StatusCode = StatusCodes.Status401Unauthorized
};
await Task.CompletedTask;
}
private bool IsTimestampValid(DateTime timestamp)
{
TimeSpan timeSpan = DateTime.UtcNow - timestamp.ToUniversalTime();
return timeSpan.TotalSeconds <= 120; // 考虑两分钟内的有效时间窗口
}
private bool ValidateSignature(string timestamp, string signature, string secretKey, string data)
{
string secretpost = $"{secretKey}{timestamp}{data}";
string calculatedMd5 = SecretHepler.EncryptToMD5Lowercase32(secretpost);
return calculatedMd5.ToUpper() == signature.ToUpper();
}
}
标签:body,return,string,postData,timestamp,await,MVC,actionContext,API From: https://www.cnblogs.com/bugenniduobb/p/18086641