管杀不管埋?! 如何在浏览器中访问 .NET 8 保护的 Swagger UI 终结点?

.NET8的新特性使SwaggerUI受保护,但缺乏浏览器访问的解决方案。文章探讨了如何通过修改SwaggerUI配置,使用JavaScript在浏览器请求中添加JWT令牌,以实现访问受保护的SwaggerUI终结点。
摘要由CSDN通过智能技术生成

目录

官方示例

问题

探索

解决

总结


.NET 8 引入了一项新特性:调用 MapSwagger().RequireAuthorization 来保护 Swagger UI 终结点。这是一个很有用的功能,可以防止未经授权的用户访问 API 文档。

但是,这也带来了一个问题:如何在浏览器中访问受保护的 Swagger UI 终结点?

官方示例

官方文档给出了保护 swagger 终结点的示例代码:

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);
}

在上面的代码中,/weatherforecast 终结点不需要授权,但 Swagger 终结点需要授权。

以下 Curl 传递 JWT 令牌来访问 Swagger UI 终结点:

curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/swagger/v1/swagger.json

问题

虽然使用 Curl 可以访问 swagger.json,但是这并不是一个方便的方式。

一般来说,我们更倾向于使用浏览器来查看 API 文档。但是,使用浏览器访问的效果如下:

图片

因为浏览器请求swagger.json时没法传递 JWT 令牌。

搜索了一下,官网没有提供解决方案,网上也没有人说碰到了这个问题。

这是一个值得关注的问题,因为它影响了开发者的体验和效率。

为了解决这个问题,我们需要找到一种方法,让浏览器请求swagger.json时能够携带 JWT 令牌。

探索

查看swagger/index.html的源代码,我们发现swagger.json是通过一个 JavaScript 函数加载的。

window.onload函数中找到这样一段:

// Parse and add interceptor functions
var interceptors = JSON.parse('{"RequestInterceptorFunction":null,"ResponseInterceptorFunction":null}');
if (interceptors.RequestInterceptorFunction)
    configObject.requestInterceptor = parseFunction(interceptors.RequestInterceptorFunction);

RequestInterceptorFunction这个名字可以猜测,它是用来拦截请求的

但是现在它的值为 null, 那么怎么为RequestInterceptorFunction赋值呢?

那只能在注册 Swagger UI 的位置了。

解决

app.UseSwaggerUI方法中,我们找到了RequestInterceptorFunction属性,它的帮助文档里的示例如下:

/// Ex: "function (req) { req.headers['MyCustomHeader'] = 'CustomValue'; return req; }"

这正是我们想要的效果!

请求swagger.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("\r\n",""));

当请求swagger.json时,我们将浏览器地址栏中的token参数添加到Authorization Header中。

图片

总结

.NET 8 引入了一项新特性:调用 MapSwagger().RequireAuthorization 来保护 Swagger UI 终结点。这是一个很有用的功能,可以防止未经授权的用户访问 API 文档。

但是,官方并没提供如何在浏览器中优雅地访问受保护的 Swagger UI 终结点的方案。

我们通过修改 Swagger UI 的配置,实现了在浏览器中携带 JWT 令牌访问 Swagger UI 的功能。

引入地址 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值