我正在尝试使集成测试针对受保护的api端点进行工作。 我的测试调用了IDS连接/令牌端点,并获取了有效令牌。当我使用它来调用受保护的api时,invalid_token总是会失败。 (该api也是IDS本地的)
如果我手动调试IDS并使用邮递员获取令牌,然后手动设置令牌并使用邮递员调用受保护的api,则它会正常工作。
我怀疑IDS验证代码的内部内容无法到达发现端点,因为它正在旋转自己的HttpClient。我知道WebApplicationFactory客户端是HttpClient的特殊实现。
有没有一种方法可以在配置/启动期间将WebApplicationFactory客户端注入IDS,以便它可以正常工作?
还是有一种方法可以使伪造的授权端点仅验证Auth标头中发送的任何令牌?
我希望我的集成测试能够针对api进行工作,如果它实际上验证了令牌,那真是太好了,但如果我不能伪造它,那就太好了。
谢谢。
答案 0 :(得分:1)
以惯常的方式,在我问了一些问题之后,我立即弄清楚了。这是基于另一个问题的简单解决方案,其答案有些复杂(How can I set my IdentityServer4 BackChannelHandler from within an xUnit integration test using WebApplicationFactory?)。
在您的Startup.cs中添加一个静态属性:
string query = "INSERT INTO flexTable SELECT MapJSONExtractor(@flexDataToInsert) as event"
var connection = GetConnection(); // returns OdbcConnection
var command = GetCommand(connection, queryString.ToString()); // returns OdbcCommand
OdbcParameter param = command.Parameters.Add("@flexDataToInsert", OdbcType.NText, 2048);
param.Value = data; // long json to insert
await command.ExecuteNonQueryAsync()
然后将其添加到您的/// <summary>
/// For integrationtesting set this to Factory.Server.CreateHandler()
/// </summary>
public static HttpMessageHandler JwtBackChannelHandler { get; set; }
选项中:
.AddIdentityServerAuthentication()
在实现if (JwtBackChannelHandler != null)
{
options.JwtBackChannelHandler = JwtBackChannelHandler;
}
的测试类的构造函数中,添加以下内容:
IClassFixture<WebApplicationFactory<Startup>>
这将允许您调用令牌端点并接收真实令牌,并将其用作集成测试中的身份验证标头。热得发呆。
答案 1 :(得分:0)
这个答案是针对@liqSTAR 关于如何忽略 IdentitiyServer 4 并在集成测试中伪造授权的。
创建一个如下所示的类:
public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public TestAuthHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var context = Context;
List<Claim> claims;
if (context.Request.Headers.Keys.Contains("my-name"))
{
var name = context.Request.Headers["my-name"].First();
var id = context.Request.Headers.Keys.Contains("my-id") ? context.Request.Headers["my-id"].First() : "";
claims = new List<Claim>
{
new Claim(ClaimTypes.Name, name),
new Claim(ClaimTypes.NameIdentifier, id),
};
}
else
{
claims = new List<Claim> { new Claim(ClaimTypes.Name, "Test user") };
}
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
context.User = principal;
var ticket = new AuthenticationTicket(principal, "Test");
var result = AuthenticateResult.Success(ticket);
return Task.FromResult(result);
}
}
然后在继承自 override void ConfigureWebHost(IWebHostBuilder builder)
的自定义类中的 WebApplicationFactory<TStartup>
添加
services.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>("Test", options => {});
到 builder.ConfigureServices(services => {
部分。
然后在你的测试类中添加
Client.DefaultRequestHeaders.Add("my-id", "1234");
Client.DefaultRequestHeaders.Add("my-name", "Test_User");
当您想要模拟用户时,将其添加到您的 ctor 或测试方法,以便在您的控制器尝试使用 Authorize
执行某些操作时 User
属性起作用。 (Client
是我为 Factory.CreateClient();
提供的便利属性)
这样做的好处是,如果您不希望通过授权用户,请不要设置 my-id 和 my-name 标头。
我希望这能帮助您朝着正确的方向前进。