我是 Swagger 新手。我正在使用 OpenAPI 3.0.2。
当我运行 Swagger UI 时,顶部和每个 API 都会出现授权按钮,但它们不起作用。当我单击它们时,我可以在 apiKey 框中输入任何文本,它会接受它并表示我已获得授权。但是没有 API 起作用,它们都返回 401
这里是Startup.ConfigureServices中的相关代码
services.AddAuthentication(
x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}
)
.AddJwtBearer(
x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Audience"],
};
}
);
services.AddSwaggerGen(
setupAction =>
{
setupAction.SwaggerDoc(
"LibraryOpenApiSpecification",
new Microsoft.OpenApi.Models.OpenApiInfo()
{
Title = "Library API",
Version = "2.0",
Description = "Text",
Contact = new Microsoft.OpenApi.Models.OpenApiContact()
{
Email = "[email protected]",
Name = "user1",
Url = new Uri("http://www.google.com")
}
}
);
setupAction.AddSecurityDefinition(
"Bearer",
new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme."
}
);
setupAction.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
}
);
var xmlCommentsFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlCommentFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentsFile);
setupAction.IncludeXmlComments(xmlCommentFullPath);
}
);
该代码不是我的,是由其他开发人员引入的。 如果需要,我将提供更多代码和信息
这是一个工作示例:
services.AddSwaggerGen(
c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "ApiPlayground", Version = "v1" });
c.AddSecurityDefinition(
"token",
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer",
In = ParameterLocation.Header,
Name = HeaderNames.Authorization
}
);
c.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "token"
},
},
Array.Empty<string>()
}
}
);
}
);
配置完成后,Swagger UI 会为您提供一个进行身份验证的按钮
一旦您填写了令牌并发送请求,它就会将其发送到
Authorization
标头中。
现在,应用程序必须为每个请求解析和验证此令牌,因此您必须在
Startup.Configure
方法中启用身份验证中间件。
app.UseAuthentication();
app.UseAuthorization();
然后,如果令牌通过验证,您应该能够使用
HttpContext.User
属性访问用户。
如果您仍然收到 401 错误,这意味着令牌验证存在问题,请检查您是否已在
Startup.Configure
方法中配置了授权服务:
services.AddAuthorization(
options => options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).Build()
);
这将要求所有请求进行身份验证,除非使用
[Authorize]
(或 [AllowAnonymous]
)属性设置另一个授权策略。这将确保令牌被解析和验证。
这是一个用于签名和验证令牌的端到端 API。
internal class HardCodedConfiguration
{
public static SymmetricSecurityKey SigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(
"alongrandomstringhere.11b48736983e87c5cff022c462849ca5b7c5e99b76d81e9707fa35e76024cba8"
)
);
public static SigningCredentials SigningCredentials => new SigningCredentials(
SigningKey,
SecurityAlgorithms.HmacSha256
);
}
[ApiController]
[Route("")]
public class HelloController : ControllerBase
{
[AllowAnonymous]
[HttpGet("token")]
public ActionResult SignToken()
{
var token = new JwtSecurityTokenHandler().WriteToken(
new JwtSecurityToken(
claims: new List<Claim>()
{
new Claim("name", "abdusco")
},
expires:DateTime.Now.AddHours(1),
signingCredentials: HardCodedConfiguration.SigningCredentials
)
);
return Ok(token);
}
[HttpGet]
public IActionResult AuthorizedEndpoint()
{
return Ok(User.Claims.Select(c => new { c.Type, c.Value }).ToList());
}
}
// inside Startup class
public void ConfigureServices(IServiceCollection services)
{
// swagger configuration
// ...
services.AddControllers();
services.AddAuthorization(
options => options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).Build()
);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(
o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = HardCodedConfiguration.SigningKey,
};
}
);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
为了让 Swagger UI(.NET 6、OpenApi v3、Swashbuckle v6.5)身份验证为我工作,我必须创建一个
AuthenticationRequirementsOperationFilter
并将其添加到过滤器中,如 此 github 答案中所述。同样重要的是,关键字 bearer
在 AddSecurityDefinition
和 OpenApiSecurityScheme
中保持相同。
这是示例代码:
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(opt =>
{
opt.SwaggerDoc("v1", new OpenApiInfo { Title = "My Api", Version = "v1" });
opt.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
In = ParameterLocation.Header,
Scheme = "bearer"
});
opt.OperationFilter<AuthenticationRequirementsOperationFilter>();
});
}
}
public class AuthenticationRequirementsOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
operation.Security.Add(new OpenApiSecurityRequirement
{
[scheme] = new List<string>()
});
}
}