本文主要介绍一种与微信公众平台对接方式类似的,为 AspNetCore 提供的一种简易的 WebAPI 签名验证中间件。
本文相关源码和案例已开源,地址:https://github.com/sangyuxiaowu/SignAuthorization
原理说明
简易的 API url 签名验证中间件,通过简单的url参数验证请求是否合法。思路是按照微信公众平台的验证消息的确来自微信服务器[1]的方式来实现的。
访问 WebAPI 需要实现的 signature 签名流程也一样:.
1.将token、timestamp、nonce三个参数进行字典序排序2.将三个参数字符串拼接成一个字符串进行sha1加密3.开发者获得加密后的字符串可与 signature 对比
安装使用
添加包
使用包管理工具
Install-Package Sang.AspNetCore.SignAuthorization或者 .NET CLI
dotnet add package Sang.AspNetCore.SignAuthorization启用和配置
在 app.MapControllers(); 前启用这个中间件,并进行一些必要的配置。
app.UseSignAuthorization(opt => {opt.sToken = "you-api-token";});
使用验证方式
在需要签名的地方添加 SignAuthorizeAttribute。
Mini API:
app.MapGet("/weatherforecast", () =>{// your code}).WithMetadata(new SignAuthorizeAttribute());
或者:
[HttpGet][SignAuthorize]public IEnumerable<WeatherForecast> Get(){// your code}
配置说明
| 参数 | default | 说明 |
| UnauthorizedBack | {"success":false,"status":10000,"msg":"Unauthorized"} | 验证失败后的 json 返回 |
| sToken | SignAuthorizationMiddleware | API签名使用的token |
| WithPath | false | 签名时需要包含请求的路径,以 '/' 开头 |
| Expire | 5 | 签名过期时间(单位:秒) |
| nTimeStamp | timestamp | 时间戳的GET参数名 |
| nNonce | nonce | 随机数的GET参数名 |
| nSign | signature | 签名的GET参数名 |
对接访问
PHP example
$sToken = "you-api-token";$sReqTimeStamp = time();$sReqNonce = getNonce();$tmpArr = array($sToken, $sReqTimeStamp, $sReqNonce);sort($tmpArr, SORT_STRING);$sign = sha1(implode($tmpArr));$url = "http://localhost:5177/weatherforecast?timestamp=$sReqTimeStamp&nonce=$sReqNonce&signature=$sign";echo "$url\n";echo file_get_contents($url);function getNonce(){$str = '1234567890abcdefghijklmnopqrstuvwxyz';$t1='';for($i=0;$i<30;$i++){$j=rand(0,35);$t1 .= $str[$j];}return $t1;}
.Net example
var unixTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds();var sNonce = Guid.NewGuid().ToString();ArrayList AL = new ArrayList();AL.Add("you-api-token");AL.Add(unixTimestamp.ToString());AL.Add(sNonce);AL.Sort(StringComparer.Ordinal);var raw = string.Join("", AL.ToArray());using System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create();byte[] encry = sha1.ComputeHash(Encoding.UTF8.GetBytes(raw));string sign = string.Join("", encry.Select(b => string.Format("{0:x2}", b)).ToArray()).ToLower();var client = new HttpClient();string jsoninfo = await client.GetStringAsync($"http://localhost:5177/weatherforecast?timestamp={unixTimestamp}&nonce={sNonce}&signature={sign}");
使用案例
在开源仓库中,提供了两个 weatherforecast 的接入验证样例 TestWebMiniAPI 和 TestWebAPI,引入 nuget 包 Sang.AspNetCore.SignAuthorization 后,仅需要修改很少的部分就可以实现 API 访问的 URL 验签。