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 帖子,它向您展示了正确的方法。
| 归档时间: |
|
| 查看次数: |
7980 次 |
| 最近记录: |