不要在测试中验证 JWT 过期
Posted
技术标签:
【中文标题】不要在测试中验证 JWT 过期【英文标题】:Do not validate JWT expiration in tests 【发布时间】:2021-12-17 22:10:38 【问题描述】:我正在使用 JWT 身份验证为我的 Web 服务编写集成测试。我想用从真实服务收到的令牌对其进行测试。问题是真正的令牌会在 1 小时后过期。
一种可能的方法是在下面的Startup
类的AddJwtBearer
中设置options.TokenValidationParameters.ValidateLifetime
。
不过Startup
类也是一个待测试的代码,所以我不想更改或替换它进行测试。
有没有一种简洁的方法来测试除过期之外的所有 JWT 验证逻辑?
我的项目代码:
public class Startup
public void ConfigureServices(IServiceCollection services)
services.AddControllers();
services.AddAuthentication("JWT")
.AddJwtBearer("JWT", options =>
options.Authority = "https://my-real-identity-server.com/";
options.Audience = "...";
// I don't want to disable lifetime validation in real life
// options.TokenValidationParameters.ValidateLifetime = false;
);
// Other stuff
public void Configure(IApplicationBuilder app) => app
.UseRouting()
.UseAuthentication()
.UseAuthorization()
.UseEndpoints(endpoints => endpoints.MapControllers());
public class TestController : ControllerBase
[Authorize]
[HttpGet("/validate")]
public string Get() => "success";
我的测试代码:
public class HostBuilderTests
private IHost testHost;
private CancellationTokenSource cancel;
private HttpClient client;
[SetUp]
public async Task ShouldReturnStatus()
testHost = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
webBuilder
.UseStartup<Startup>()
.UseTestServer())
.ConfigureServices(services => services
.AddLogging(b => b.ClearProviders().AddNUnit()))
.Build();
cancel = new CancellationTokenSource(10000);
var server = testHost.Services.GetRequiredService<IServer>()
.ShouldBeOfType<TestServer>();
await testHost.StartAsync(cancel.Token);
client = server.CreateClient();
[TearDown]
public async Task TearDown()
await testHost.StopAsync(cancel.Token);
client.Dispose();
testHost.Dispose();
cancel.Dispose();
[Test]
[TestCase("<<JWT token copied from the real service>>")]
public async Task StatusShouldBeOk(string realToken)
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", realToken);
using var response = await client.GetAsync("/validate", cancel.Token);
response.StatusCode.ShouldBe(HttpStatusCode.OK);
【问题讨论】:
AddJwtBearer lambda 中有很多不同的“验证...”属性。您已经为权威和观众设置了两个。其中一个是在谈论“终身”还是“到期”?例如:***.com/a/59014327/1043380 @gunr2171 好点,看看我的编辑。 您是在 AddJwtBearer 中对所有选项进行硬编码,还是通过配置设置它们(您应该这样做)? @gunr2171 是的,我愿意。所以解决方案是为测试项目使用不同的应用配置,太好了! 我会警惕这样做 - 如果您进行不同的配置,您可能会引入安全错误。 【参考方案1】:最后我找到了一种管理身份验证处理程序选项的简单方法:
身份验证方案是一个名称,对应于:
身份验证处理程序。 用于配置特定处理程序实例的选项。
见MSDN。
因此,在测试设置中指定身份验证方案名称 "JWT"
作为选项实例名称后配置 JwtBearerOptions
就足够了:
testHost = Host.CreateDefaultBuilder()
// other setup
.ConfigureServices(services => services
.PostConfigure<JwtBearerOptions>("JWT",
op => op.TokenValidationParameters.ValidateLifetime = false)
// other setup
).Build();
也可以传递null
而不是"JWT"
,因为它写在comments:
// Null name is used to configure all named options.
【讨论】:
以上是关于不要在测试中验证 JWT 过期的主要内容,如果未能解决你的问题,请参考以下文章