默认情况下,JwtBearer 身份验证方案将使用ConfigurationManager 用于在.well-known/openid-configuration 公开的配置。如果你没有通过设置JwtBearerOptions.ConfigurationManager属性显式配置实例,那么它会自动创建一个after your configuration:
var httpClient = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
httpClient.Timeout = options.BackchannelTimeout;
httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(httpClient) { RequireHttps = options.RequireHttpsMetadata });
您可以在之前显式设置配置管理器,这样这段代码就不会运行。这样,您可以提供自己的实现或正确授权其请求的HttpClient。
如果你看代码,还有一个BackchannelHttpHandler。这是用于反向通道通信的HttpClientHandler。反向通道请求是所有与权限通信的请求;所以不仅是配置端点,还有诸如 OAuth 的 userinfo 端点之类的东西。由于 JWT 没有任何反向通道通信,因此在这种情况下您无需担心它,但因为您也可以配置它,例如OAuth,记住这一点很重要。
因此,使用 BackchannelHttpHandler,您可以指定凭据:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
options.BackchannelHttpHandler = new HttpClientHandler()
{
UseDefaultCredentials = true,
};
// …
});
如果您需要其他凭据,例如使用Authorization HTTP 标头,您还可以提供自己的DelegatingHandler,在将请求委托给普通HttpClientHandler 之前添加HTTP 标头。像这样的:
public class AuthorizingHandler : DelegatingHandler
{
private readonly string _headerValue;
public AuthorizingHandler(HttpMessageHandler inner, string headerValue)
: base(inner)
{
_headerValue = headerValue;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("Authorization", _headerValue);
return base.SendAsync(request, cancellationToken);
}
}
var innerHandler = new HttpClientHandler();
var headerValue = "Bearer foobar";
options.BackchannelHttpHandler = new AuthorizingHandler(innerHandler, headerValue);
另一种选择是直接使用JwtBearerOptions.Configuration 提供配置。但这当然需要您以其他方式将设置与权限同步,因此这可能不是一个好的选择。