You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8中如何保护swagger/1.0/swagger.json端点?

如何在.NET 8中保护Swagger JSON端点

我在ReactJS应用中创建了自定义SwaggerUI(index.html)文件,可通过myapplication.com/docs/swagger/index.html访问。由于该路由经过/docs/路径,已应用STS认证。但SwaggerUI从/swagger/v1/swagger.json端点获取数据,当前该端点未受保护,任何人都可通过myapplication.com/swagger/v1/swagger.json访问它。请问如何在.NET 8中保护这个端点?

ReactJS代码

App.tsx

import React, { useState } from 'react'
import SwaggerUI from 'swagger-ui-react'
import 'swagger-ui-react/swagger-ui.css'
import { GettingStartedSection } from 'sections/getting-started'

const App = () => {
    const [activeItem, setActiveItem] = useState<string | undefined>('getting-started')
    
    return (
        <CustomPageWrapper>
            <div id="App" className="App">                

                <DocumentationWrapper>
                    <GettingStartedSection />
                    <SwaggerUI layout="BaseLayout" url="/v1/swagger/1.0/swagger.json" />
                    <HandlingErrorsAndVersioningSection />
                </DocumentationWrapper>
            </div>
        </CustomPageWrapper>
    )
}

export default App

root-app.tsx

import React from 'react'
import { Route, BrowserRouter, Switch } from 'react-router-dom'
import { AuthContextProvider } from './contexts/auth.context'
import { AuthzContextProvider } from './contexts/authz.context'
import { UserContextProvider } from './contexts/user'
import { AuthCallbackPage, LogoutCallbackPage, LogoutPage, SilentRenewPage } from './pages/auth'
import { AuthorizedRoute } from './routes/authorized-route'
import App from './App'

const RootApp = () => {
    const returnEmptyComponent = () => <></>

    return (
        <AuthContextProvider>
            <AuthzContextProvider>
                <BrowserRouter>
                    <UserContextProvider>
                        <Switch>
                            <Route path="/docs/auth/callback" component={AuthCallbackPage} />
                            <Route path="/docs/auth/silent-renew" component={SilentRenewPage} />
                            <Route exact path="/account/logout" component={LogoutPage} />
                            <Route exact path="/docs/auth/logout/callback" component={LogoutCallbackPage} />                            
                            <AuthorizedRoute path="/*" component={App} />
                        </Switch>
                    </UserContextProvider>
                </BrowserRouter>
            </AuthzContextProvider>
        </AuthContextProvider>
    )
}

export default RootApp

C#代码

app.UseSwagger();

 app.UseSwaggerUI(options =>
 {
     // build a swagger endpoint for each discovered API version
     bool isPathPrefixDefined = !string.IsNullOrWhiteSpace(swaggerOptions?.PathPrefix);

     if (isPathPrefixDefined)
     {
         foreach (var description in provider.ApiVersionDescriptions)
         {
             options.SwaggerEndpoint($"{swaggerOptions.PathPrefix}/swagger/{description.GroupName}/swagger.json",
                 $"{swaggerOptions.GeneratedJsonName}  {description.GroupName.ToUpperInvariant()}");
         }
     }
     else
     {
         foreach (var description in provider.ApiVersionDescriptions)
         {
             options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
         }
     }

     if (swaggerOptions.IncludeAuthentication)
     {
         options.OAuthClientId(swaggerOptions.SecurityDefinition.ClientId);
         options.OAuthClientSecret(swaggerOptions.SecurityDefinition.ClientSecret);
     }
 });

解决方案

方法1:为Swagger JSON端点添加授权中间件

在.NET 8的管道中,在UseSwagger()之后添加授权规则,限制只有通过STS认证的用户才能访问/swagger/*路径:

// 先配置授权服务(如果还没配置)
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("SwaggerAccess", policy =>
    {
        // 要求用户已通过STS认证
        policy.RequireAuthenticatedUser();
        // 如果需要特定角色或权限,可添加以下规则
        // policy.RequireRole("Admin");
        // policy.RequireClaim("scope", "api.read");
    });
});

// 在UseSwagger之后添加授权中间件
app.UseSwagger();

// 为Swagger JSON端点应用授权策略
app.MapWhen(context => context.Request.Path.StartsWithSegments("/swagger"), appBuilder =>
{
    appBuilder.UseAuthorization();
    appBuilder.Use(async (context, next) =>
    {
        var result = await context.AuthenticateAsync();
        if (!result.Succeeded)
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            return;
        }

        var authorizationResult = await context.AuthorizeAsync("SwaggerAccess");
        if (!authorizationResult.Succeeded)
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            return;
        }

        await next();
    });
});

app.UseSwaggerUI(...); // 保持原有SwaggerUI配置

方法2:将Swagger JSON端点迁移到/docs/路径下

既然你的SwaggerUI已经在/docs/路径下受保护,可以把Swagger JSON的路径也调整到/docs/前缀下,这样就能复用现有的STS认证规则:

  1. 修改Swagger配置,设置PathPrefix为/docs:
// 假设swaggerOptions是你的配置对象,设置PathPrefix
swaggerOptions.PathPrefix = "/docs";

app.UseSwagger(options =>
{
    // 设置Swagger JSON的路径前缀
    options.RouteTemplate = "docs/swagger/{documentName}/swagger.json";
});

app.UseSwaggerUI(options =>
{
    bool isPathPrefixDefined = !string.IsNullOrWhiteSpace(swaggerOptions?.PathPrefix);

    foreach (var description in provider.ApiVersionDescriptions)
    {
        options.SwaggerEndpoint($"/docs/swagger/{description.GroupName}/swagger.json",
            $"{swaggerOptions.GeneratedJsonName}  {description.GroupName.ToUpperInvariant()}");
    }

    // 保持原有OAuth配置
    if (swaggerOptions.IncludeAuthentication)
    {
        options.OAuthClientId(swaggerOptions.SecurityDefinition.ClientId);
        options.OAuthClientSecret(swaggerOptions.SecurityDefinition.ClientSecret);
    }
});
  1. 修改React代码中的SwaggerUI url,匹配新的路径:
<SwaggerUI layout="BaseLayout" url="/docs/swagger/1.0/swagger.json" />

这样Swagger JSON的路径就变成了myapplication.com/docs/swagger/1.0/swagger.json,会自动继承/docs/路径下的STS认证保护,无需额外配置授权规则。

方法3:使用端点路由直接保护Swagger JSON

在.NET 8中,也可以直接通过端点路由来保护Swagger的JSON端点:

app.UseSwagger();

// 保护Swagger JSON端点
app.MapGet("/swagger/{documentName}/swagger.json", async context =>
{
    var result = await context.AuthenticateAsync();
    if (!result.Succeeded)
    {
        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
        return;
    }

    // 如果需要权限验证,添加授权检查
    var authResult = await context.AuthorizeAsync("SwaggerAccess");
    if (!authResult.Succeeded)
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        return;
    }

    // 转发请求到原始Swagger中间件
    await app.ApplicationServices.CreateScope().ServiceProvider
        .GetRequiredService<SwaggerMiddleware>()
        .Invoke(context);
}).RequireAuthorization("SwaggerAccess");

app.UseSwaggerUI(...);

内容的提问来源于stack exchange,提问作者Mariselvam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:24:52