管杀不管埋?! 如何在浏览器中访问

.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 的功能。

© 版权声明
THE END
喜欢就支持一下吧
点赞79 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容