添加授权 Header (Authorization: Bearer {access_token}) 到 Ocelot API 网关中的特定路由
Adding Authorization Header (Authorization: Bearer {access_token}) to specific route in Ocelot API Gateway
我有一个 Web 应用程序通过 Ocelot API 网关向不同的 API 发出请求。其中一个端点需要通过 JWT 进行身份验证,作为授权 header 以“授权:Bearer {access_token}”格式发送(“Bearer”关键字将其标识为 bearer/token 身份验证方案) .此令牌特定于应用程序,不用于通过网关(使用不同的身份验证方案)进行身份验证,而是作为声明存储在应用程序的安全 HttpOnly cookie 中。
虽然 Ocelot 确实支持将声明转换为 headers (https://ocelot.readthedocs.io/en/latest/features/claimstransformation.html),
"AddHeadersToRequest": {
"HeaderName": "Claims[ClaimName] > value[0] > |"
},
它只支持一个值,不支持动态 headers/string 串联。也就是说
"AddHeadersToRequest": {
"Authorization": "Bearer Claims[ClaimName] > value[0] > |"
},
将不起作用(这样的请求显然会导致错误 401)。所以我的问题是,如何向特定的 Ocelot 路由添加适当的授权 header/bearer 令牌?
委派处理程序(https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=net-5.0, https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html
),在请求发送前添加“stuff”,结果证明非常适合这个任务。由于 Ocelot 声明转换发生在它们被调用之前,这只是将声明转换为 header 的问题,然后连接它们的值并将它们添加为新的 header.
第一次编辑 ocelot.json:
"AddHeadersToRequest": {
"AccessToken": "Claims[AccessToken] > value[0] > |"
},
"DelegatingHandlers": [
"HeaderDelegatingHandler"
]
然后创建一个 HeaderDelegatingHandler class 继承自 DelegatingHandler:
public class HeaderDelegatingHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HeaderDelegatingHandler (IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IEnumerable<string> headerValues;
if (request.Headers.TryGetValues("AccessToken", out headerValues))
{
string accessToken = headerValues.First();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Remove("AccessToken");
}
return await base.SendAsync(request, cancellationToken);
}
}
记得将委托处理程序添加到 ConfigureServices(可以设置为全局或不设置):
services.AddOcelot()
.AddDelegatingHandler<HeaderDelegatingHandler>();
Tom Pallister (https://github.com/ThreeMammals/Ocelot/issues/468), rh101's (https://github.com/ThreeMammals/Ocelot/issues/1267#issuecomment-649299048) and PaulD's (https://whosebug.com/a/60609784/2768479) 的帖子阐明了这个问题。
我有一个 Web 应用程序通过 Ocelot API 网关向不同的 API 发出请求。其中一个端点需要通过 JWT 进行身份验证,作为授权 header 以“授权:Bearer {access_token}”格式发送(“Bearer”关键字将其标识为 bearer/token 身份验证方案) .此令牌特定于应用程序,不用于通过网关(使用不同的身份验证方案)进行身份验证,而是作为声明存储在应用程序的安全 HttpOnly cookie 中。
虽然 Ocelot 确实支持将声明转换为 headers (https://ocelot.readthedocs.io/en/latest/features/claimstransformation.html),
"AddHeadersToRequest": {
"HeaderName": "Claims[ClaimName] > value[0] > |"
},
它只支持一个值,不支持动态 headers/string 串联。也就是说
"AddHeadersToRequest": {
"Authorization": "Bearer Claims[ClaimName] > value[0] > |"
},
将不起作用(这样的请求显然会导致错误 401)。所以我的问题是,如何向特定的 Ocelot 路由添加适当的授权 header/bearer 令牌?
委派处理程序(https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=net-5.0, https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html ),在请求发送前添加“stuff”,结果证明非常适合这个任务。由于 Ocelot 声明转换发生在它们被调用之前,这只是将声明转换为 header 的问题,然后连接它们的值并将它们添加为新的 header.
第一次编辑 ocelot.json:
"AddHeadersToRequest": {
"AccessToken": "Claims[AccessToken] > value[0] > |"
},
"DelegatingHandlers": [
"HeaderDelegatingHandler"
]
然后创建一个 HeaderDelegatingHandler class 继承自 DelegatingHandler:
public class HeaderDelegatingHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HeaderDelegatingHandler (IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IEnumerable<string> headerValues;
if (request.Headers.TryGetValues("AccessToken", out headerValues))
{
string accessToken = headerValues.First();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Remove("AccessToken");
}
return await base.SendAsync(request, cancellationToken);
}
}
记得将委托处理程序添加到 ConfigureServices(可以设置为全局或不设置):
services.AddOcelot()
.AddDelegatingHandler<HeaderDelegatingHandler>();
Tom Pallister (https://github.com/ThreeMammals/Ocelot/issues/468), rh101's (https://github.com/ThreeMammals/Ocelot/issues/1267#issuecomment-649299048) and PaulD's (https://whosebug.com/a/60609784/2768479) 的帖子阐明了这个问题。