我在mac上的aspnet核心应用程序中运行了RSA256签名代码。
不过,在我的单元测试中,我得到了错误。
'CspParameters' requires Windows Cryptographic API (CAPI) ONLY when running a unit test
我是否需要在单元测试中模拟或提供一些aspnet'ish来实现这一点?
public class SessionIdSecureDataFormat : ISessionIdSecureDataFormat
{
private readonly IEnumerable<SecurityKey> _issuerSigningKeys;
private readonly SecurityKey _privateKey;
private readonly string _issuer;
private readonly string _audience;
public SessionIdSecureDataFormat(IEnumerable<SecurityKey> issuerSigningKeys, SecurityKey privateKey,
string issuer, string audience)
{
_issuerSigningKeys = issuerSigningKeys;
_privateKey = privateKey;
_issuer = issuer;
_audience = audience;
}
public string Protect(string data)
{
if (data == null)
{
return null;
}
var securityTokenDescriptor = new SecurityTokenDescriptor
{
SigningCredentials = new SigningCredentials(_privateKey, "RS256"),
Issuer = _issuer,
Audience = _audience,
};
var handler = new JwtSecurityTokenHandler();
var jwt = handler.CreateJwtSecurityToken(securityTokenDescriptor);
jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Jti, data));
return handler.WriteToken(jwt);
}
public string Protect(string data, string purpose)
{
return this.Protect(data);
}
public string Unprotect(string protectedText)
{
if (protectedText == null)
{
return null;
}
var handler = new JwtSecurityTokenHandler();
var validationContext = new TokenValidationParameters
{
RequireExpirationTime = false,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
IssuerSigningKeys = _issuerSigningKeys,
ValidIssuer = _issuer,
ValidAudience = _audience
};
handler.ValidateToken(protectedText, validationContext, out var jwt);
return jwt.Id;
}
public string Unprotect(string protectedText, string purpose)
{
//TODO - It's not clear if we are supposed to check if the purpose matches our declared purpose. No documentation.
return this.Unprotect(protectedText);
}
}
单元测试的设置,其中Protect
失败。
public class SessionJwtDataProtectorTests
{
private readonly byte[] _encodedJwt;
private readonly byte[] _sessionIdOriginal;
private readonly SessionJwtDataProtector _sessionJwtDataProtector;
private readonly Mock<IServiceProvider> _provider = new Mock<IServiceProvider>();
public SessionJwtDataProtectorTests()
{
var sessionIdSecureDataFormat = CreateSessionIdSecureDataFormat();
_provider.Setup(p => p.GetService(typeof(ISessionJwtDataProtector)))
.Returns(new SessionJwtDataProtector(_provider.Object, sessionIdSecureDataFormat));
_sessionJwtDataProtector = new SessionJwtDataProtector(_provider.Object, sessionIdSecureDataFormat);
var sessionId = Guid.NewGuid().ToString();
_sessionIdOriginal = Encoding.UTF8.GetBytes(sessionId);
_encodedJwt = _sessionJwtDataProtector.Protect(_sessionIdOriginal);
}
private static SessionIdSecureDataFormat CreateSessionIdSecureDataFormat()
{
var issuerKeys = new List<RsaSecurityKey>();
foreach (var pemKey in StaticSessionPemKeys.ISSUER_KEYS)
{
RSA rsa = RSAHelper.PublicKeyFromPemString(pemKey.Pem);
issuerKeys.Add(new RsaSecurityKey(rsa) {KeyId = pemKey.KeyId});
}
RSA privateKeyProvider = RSAHelper.PrivateKeyFromPemString(StaticSessionPemKeys.PRIVATE_KEY.Pem);
var privateKey = new RsaSecurityKey(privateKeyProvider)
{KeyId = StaticSessionPemKeys.PRIVATE_KEY.KeyId};
return new SessionIdSecureDataFormat(issuerKeys, privateKey, "ABC", "ABC");
}
}
问题似乎是依赖于
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.3.0" />
请参阅https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1038
我通过删除此引用而改为引用来解决此问题
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.1"/>
您能将Microsoft.IdentityModel.Protocols.OpenIdConnect升级到5.4.0版本吗?
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="5.4.0" />