如何通过RouteClaimsRequirement允许多个角色访问路由
How to allow multiple roles to access route through RouteClaimsRequirement
在常规类型的情况下,如果路线可用,比如仅对“高级”用户,ocelot.global.json
将 RouteClaimsRequirement
像这样:
"RouteClaimsRequirement" : { "Role" : "Premium" }
这会被翻译成 KeyValuePair<string, string>()
,而且效果很好。
但是,如果我要为两种类型的用户打开一条路线,例如。 “常规”和“高级”,我究竟该如何实现?
我找到了一种通过覆盖默认 Ocelot 中间件的方法。以下是一些有用的代码片段:
首先,覆盖Startup.cs中Configuration()中默认的AuthorizationMiddleware:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var config = new OcelotPipelineConfiguration
{
AuthorisationMiddleware
= async (downStreamContext, next) =>
await OcelotJwtMiddleware.CreateAuthorizationFilter(downStreamContext, next)
};
app.UseOcelot(config).Wait();
}
如您所见,我在上面使用自定义的 OcelotJwtMiddleware class。这是class,粘贴:
public static class OcelotJwtMiddleware
{
private static readonly string RoleSeparator = ",";
public static Func<DownstreamContext, Func<Task>, Task> CreateAuthorizationFilter
=> async (downStreamContext, next) =>
{
HttpContext httpContext = downStreamContext.HttpContext;
var token = httpContext.Request.Cookies[JwtManager.AuthorizationTokenKey];
if (token != null && AuthorizeIfValidToken(downStreamContext, token))
{
await next.Invoke();
}
else
{
downStreamContext.DownstreamResponse =
new DownstreamResponse(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
};
private static bool AuthorizeIfValidToken(DownstreamContext downStreamContext, string jwtToken)
{
IIdentityProvider decodedObject = new JwtManager().Decode<UserToken>(jwtToken);
if (decodedObject != null)
{
return downStreamContext.DownstreamReRoute.RouteClaimsRequirement["Role"]
?.Split(RoleSeparator)
.FirstOrDefault(role => role.Trim() == decodedObject.GetRole()) != default;
}
return false;
}
}
JwtManager class 这只是我使用默认的 Jwt NuGet 包制作的小实用程序,没什么特别的。此外,JWT 被存储为 Cookie,这并不安全,但在这里无关紧要。如果您碰巧复制粘贴了您的代码,您将遇到与此相关的小错误,但只需将其切换为您自己的身份验证令牌实现即可。
在这 2 个片段被实施之后,ocelot.global.json 可以有这样的 RouteClaimsRequirement:
"RouteClaimsRequirement" : { "Role" : "Premium, Regular" }
这将识别在其 Cookie 中使用普通版和高级版的客户。
在常规类型的情况下,如果路线可用,比如仅对“高级”用户,ocelot.global.json
将 RouteClaimsRequirement
像这样:
"RouteClaimsRequirement" : { "Role" : "Premium" }
这会被翻译成 KeyValuePair<string, string>()
,而且效果很好。
但是,如果我要为两种类型的用户打开一条路线,例如。 “常规”和“高级”,我究竟该如何实现?
我找到了一种通过覆盖默认 Ocelot 中间件的方法。以下是一些有用的代码片段:
首先,覆盖Startup.cs中Configuration()中默认的AuthorizationMiddleware:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var config = new OcelotPipelineConfiguration
{
AuthorisationMiddleware
= async (downStreamContext, next) =>
await OcelotJwtMiddleware.CreateAuthorizationFilter(downStreamContext, next)
};
app.UseOcelot(config).Wait();
}
如您所见,我在上面使用自定义的 OcelotJwtMiddleware class。这是class,粘贴:
public static class OcelotJwtMiddleware
{
private static readonly string RoleSeparator = ",";
public static Func<DownstreamContext, Func<Task>, Task> CreateAuthorizationFilter
=> async (downStreamContext, next) =>
{
HttpContext httpContext = downStreamContext.HttpContext;
var token = httpContext.Request.Cookies[JwtManager.AuthorizationTokenKey];
if (token != null && AuthorizeIfValidToken(downStreamContext, token))
{
await next.Invoke();
}
else
{
downStreamContext.DownstreamResponse =
new DownstreamResponse(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
};
private static bool AuthorizeIfValidToken(DownstreamContext downStreamContext, string jwtToken)
{
IIdentityProvider decodedObject = new JwtManager().Decode<UserToken>(jwtToken);
if (decodedObject != null)
{
return downStreamContext.DownstreamReRoute.RouteClaimsRequirement["Role"]
?.Split(RoleSeparator)
.FirstOrDefault(role => role.Trim() == decodedObject.GetRole()) != default;
}
return false;
}
}
JwtManager class 这只是我使用默认的 Jwt NuGet 包制作的小实用程序,没什么特别的。此外,JWT 被存储为 Cookie,这并不安全,但在这里无关紧要。如果您碰巧复制粘贴了您的代码,您将遇到与此相关的小错误,但只需将其切换为您自己的身份验证令牌实现即可。 在这 2 个片段被实施之后,ocelot.global.json 可以有这样的 RouteClaimsRequirement:
"RouteClaimsRequirement" : { "Role" : "Premium, Regular" }
这将识别在其 Cookie 中使用普通版和高级版的客户。