Swagger 授权持有者不发送

nim*_*ris 2 authorization swagger bearer-token .net-core asp.net-core-webapi

我在 dotnet core 3.1 Web api 项目中使用 Swagger Swashbuckle,但无法向请求调用发送承载授权。我在我的ConfigureServices方法中定义了这个:

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo() { Title = "MyApi", Version = "v1" });
            // Set the comments path for the Swagger JSON and UI.
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows()
                {
                    Password = new OpenApiOAuthFlow()
                    {

                        TokenUrl = new Uri("/api/Account/Login", UriKind.Relative),
                    }
                },
                In = ParameterLocation.Header,
                Name = "Authorization",
                Scheme = "Bearer",
            });
            c.AddSecurityRequirement(new OpenApiSecurityRequirement()
            {
                {
                    new OpenApiSecurityScheme()
                    {
                        Reference = new OpenApiReference()
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        },
                        Scheme = "Bearer",
                        Type = SecuritySchemeType.Http,
                        Name = "Bearer",
                        In = ParameterLocation.Header
                    }, new List<string>()
                }
            });
        });
Run Code Online (Sandbox Code Playgroud)

运行时,我看到显示登录对话框的授权按钮: 登录对话框

记录后,API 路由显示锁定的挂锁,但当我尝试使用它们时,我看到调用已完成,但没有返回承载:

curl -X GET "http://localhost:5000/api/Account" -H "accept: */*" -H "Authorization: Bearer undefined"
Run Code Online (Sandbox Code Playgroud)

我的定义有什么问题吗?

tec*_*cla 10

在 cURL 请求中,您可以看到:-H“授权:承载未定义”。这意味着当 Swagger-UI 尝试获取将添加到请求标头的令牌时,无法找到它。

那么,这个 token 是从哪里来的,为什么 Swagger-UI 找不到它呢?令牌位于从登录端点 (/api/Account/Login) 返回的 json 中。

您必须确保从登录端点返回的 json 符合 OAuth 密码流的预期格式,如RFC6749第 4.1.4 节(访问令牌响应)中所述。

从您的登录端点,您必须返回一个 json 响应,如下所示:

{
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"bearer"
}
Run Code Online (Sandbox Code Playgroud)

这是一个常见的错误,当您序列化来自控制器的响应时,您不尊重 json 属性名称。例如:您可以返回这样的 json:

{
       "accessToken":"2YotnFZFEjr1zCsicMWpAA",
       "tokenType":"bearer"
}
Run Code Online (Sandbox Code Playgroud)

其中“accessToken”与“access_token”不同,依此类推。

这个小小的差异导致 Swagger-UI 在反序列化返回的 json 时无法找到不记名令牌。

提示:装饰响应对象的“AccessToken”属性,以便它能够正确序列化。

[JsonPropertyName("access_token")]
[JsonProperty(PropertyName = "access_token")]
public string AccessToken { get; set; }
Run Code Online (Sandbox Code Playgroud)

虽然所解释的是您问题的要点,但我想告诉您,全局添加安全要求并不是最正确的方法。通过这种方式,您可以保护所有端点,无论它们是否用 Authorize 属性修饰。

在启动时,您只需设置“安全定义”,并添加处理“安全要求”的“操作过滤器”。然后“SecurityRequirement”引用“SecurityDefinition”,然后您就不会像在示例中那样在安全要求中重复安全定义配置(方案、类型、名称、输入等)。

请参阅这篇 github 帖子,它向您展示了正确的方法。