一.项目目的:
1.使用JWT获取token,调用外部提供的接口,解决返回HTML错误信息。
错误缘由,接口服务器未能识别token,token信息不准确。
二.项目工具:
Visual Studio(开发工具),ILSpy(反编译工具),ApiPost(接口测试工具)
三.项目难点:
1.配置环境问题,Newtonsoft.Json版本不够,无法获取token。
解决方案:传送门《金蝶云星空C#使用JWT获取token(在Newtonsoft.Json 4.0的基础上,实现Newtonsoft.Json 13.0的部分方法)》
2.接口连接需要VPN,开发环境无法测试。(外部提供win10连接vpn文档,本机win7,尝试连接无果)
解决方案:在客户环境安装VisualStuido,创建控制台程序进行测试。
3.控制台一定返回错误的Html信息,ApiPost请求时而返回错误Html信息,时而返回正确信息。
解决方案:
在与外部开发人员确认没有其他接口请求验证过后,进行多次ApiPost和控制台程序测试,发现规律,进行猜测并用实践证实猜测。
a.存在ApiPost第一次请求,返回错误,第二次请求通过的情况。
b.最终猜测第一次请求为将token信息发送给服务器,第二次请求才是正式调用接口。
c.最终在代码中连续两次调用接口,只获取第二次返回信息。
四.代码如下:
1.请求接口代码:
HttpClient client = new HttpClient();
string token = ResultToken.JWTEncode("admin");
string tokenStr = $"http://服务器域名/方法?Type=QTYFD02_SYS&Code=CLBX-20221230-0004&token={token}";
Uri tokenUrl = new Uri(tokenStr);
var tokenRes = client.GetAsync(tokenUrl).Result.Content.ReadAsStringAsync().Result; //请求服务器,传输token信息
tokenRes = client.GetAsync(tokenUrl).Result.Content.ReadAsStringAsync().Result; //携带token,请求服务器接口
2.JWT获取token方法:
注意:这里使用的是JWT10.0,Newtonsoft.Json 13.0的配置环境,低版本Newtonsoft.Json 的请进入传送门,进行重写实现Newtonsoft.Json 13.0 部分方法。
public class ResultToken
{
public static string JWTEncode(string ucode)
{
var secretKey = AppSettingService.SecretKey;//获取jwt密钥,示例是存放到配置文件
if (!String.IsNullOrEmpty(secretKey))
{
var dic = new Dictionary<string, object>();
dic["systemName"] = ucode;//增加用户名到字典
var expiredTimeSpan = 1;
if (!String.IsNullOrEmpty(AppSettingService.ExpiredTimeSpan))
{
var timeSpan = AppSettingService.ExpiredTimeSpan;
if (System.Text.RegularExpressions.Regex.IsMatch(timeSpan, "^[1-9]\\d*$"))
{
expiredTimeSpan = Convert.ToInt32(timeSpan);
}
}
var jwtcreatedOver =
Math.Round((DateTime.UtcNow.AddMinutes(expiredTimeSpan) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);
dic["exp"] = jwtcreatedOver;// 指定token的生命周期。unix时间戳格式
IJwtAlgorithm algorithm = new HMACSHA512Algorithm();
//JsonSerializer serializer = new JsonNetSerializer();
//调整语句,将紫定义JsonNetSerializer类,强制转换为JWT10.0的类
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
return encoder.Encode(dic, secretKey);//返回生成的token
}
else
return "";
}
}
最终在第二次client请求接口时,返回正确接口信息。