.NET 8 引入了一项新特性:调用 (). 来保护 UI 终结点。这是一个很有用的功能,可以防止未经授权的用户访问 API 文档。
但是,这也带来了一个问题:如何在浏览器中访问受保护的 UI 终结点?
官方示例
官方文档给出了保护 终结点的示例代码:
using System.Security.Claims;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddAuthorization();
builder.Services.AddAuthentication("Bearer").AddJwtBearer();
var app = builder.Build();
//if (app.Environment.IsDevelopment())
//{
app.UseSwagger();
app.UseSwaggerUI();
//}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapSwagger().RequireAuthorization();
app.MapGet("/", () => "Hello, World!");
app.MapGet("/secret", (ClaimsPrincipal user) => $"Hello {user.Identity?.Name}. My secret")
.RequireAuthorization();
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.Run();
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
在上面的代码中,/ 终结点不需要授权,但 终结点需要授权。
以下 Curl 传递 JWT 令牌来访问 UI 终结点:
curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/swagger/v1/swagger.json
问题
虽然使用 Curl 可以访问 .json,但是这并不是一个方便的方式。
一般来说,我们更倾向于使用浏览器来查看 API 文档。但是,使用浏览器访问的效果如下:
因为浏览器请求.json时没法传递 JWT 令牌。
搜索了一下,官网没有提供解决方案,网上也没有人说碰到了这个问题。
这是一个值得关注的问题,因为它影响了开发者的体验和效率。
为了解决这个问题,我们需要找到一种方法,让浏览器请求.json时能够携带 JWT 令牌。
探索
查看/index.html的源代码,我们发现.json是通过一个 函数加载的。
在.函数中找到这样一段:
// Parse and add interceptor functions
var interceptors = JSON.parse('{"RequestInterceptorFunction":null,"ResponseInterceptorFunction":null}');
if (interceptors.RequestInterceptorFunction)
configObject.requestInterceptor = parseFunction(interceptors.RequestInterceptorFunction);
从这个名字可以猜测,它是用来拦截请求的。
但是现在它的值为 null, 那么怎么为赋值呢?
那只能在注册 UI 的位置了。
解决
在app.方法中,我们找到了属性,它的帮助文档里的示例如下:
/// Ex: "function (req) { req.headers['MyCustomHeader'] = 'CustomValue'; return req; }"
这正是我们想要的效果!
请求.json时传递 JWT 令牌。
最后实现代码如下:
var js = @"function (req) {
if(req.url.includes('swagger.json'))
{
searchParams = new URLSearchParams(window.location.search);
if (searchParams.has('token'))
{
req.headers['Authorization'] = 'Bearer '+searchParams.get('token');
}
}
return req;
}";
app.UseSwaggerUI(option=>option.Interceptors.RequestInterceptorFunction = js.Replace("rn",""));
当请求.json时,我们将浏览器地址栏中的token参数添加到 中。
总结
.NET 8 引入了一项新特性:调用 (). 来保护 UI 终结点。这是一个很有用的功能,可以防止未经授权的用户访问 API 文档。
但是,官方并没提供如何在浏览器中优雅地访问受保护的 UI 终结点的方案。
我们通过修改 UI 的配置,实现了在浏览器中携带 JWT 令牌访问 UI 的功能。
暂无评论内容