Welcome to YARP - 5.身份验证和授权
目录
Welcome to YARP - 1.认识YARP并搭建反向代理服务
- 2.1 - 配置文件(Configuration Files)
- 2.2 - 配置提供者(Configuration Providers)
- 2.3 - 配置过滤器(Configuration Filters)
介绍
说到认证和授权,相信还是有很多小伙伴把这两个东西搞混掉,毕竟两个单词也是很相近,Authentication 和 Authorization。
-
身份验证 (我是谁?)是知道用户的标识。 例如,Alice 使用她的用户名和密码登录,服务器使用该密码对 Alice 进行身份验证。
对于认证的结果会存储在
HttpContext.User
中。常见的认证方式有:Cookie、JWT、Windows、等等,可参考 ASP.NET Core 身份验证概述 -
授权 (我有什么权限?)决定是否允许用户执行操作。 例如,Alice 有权获取资源,但无权创建资源。
授权与身份验证相互独立。 但是,授权需要一种身份验证机制。常见的授权策略有:基于角色的 RBAC,基于策略的PBAC等等,可参考 ASP.NET Core 授权简介
有了上述了解,接下来我们看 YARP
的 身份验证 和 授权
反向代理可用于在将请求代理到目标服务器之前,对请求进行身份验证和授权。这可以减少目标服务器上的负载,增加一层保护,并确保在应用程序中实施一致的策略。 接下来让我们看下如何开启认证和授权。
如果有对 .NET 本身的身份验证和授权功能不了解的小伙伴,可以先去微软文档了解一下(身份验证、授权),再回来看可能会容易理解。因为 YARP 就是使用的 .NET 的认证和授权。提供策略,交给其中间件处理。
配置
可以通过 RouteConfig.AuthorizationPolicy 为每个路由指定授权策略,并且可以从配置文件的 Routes
各个部分进行绑定。与其他路由属性一样,可以在不重新启动代理的情况下修改和重新加载此属性。策略名称不区分大小写。
示例:
{
"ReverseProxy": {
"Routes": {
"route1" : {
"ClusterId": "cluster1",
"AuthorizationPolicy": "customPolicy",
"Match": {
"Hosts": [ "localhost" ]
},
}
},
"Clusters": {
"cluster1": {
"Destinations": {
"cluster1/destination1": {
"Address": "https://localhost:10001/"
}
}
}
}
}
}
授权策略使用的是 ASP.NET Core 的概念。代理提供上述配置来为每个路由指定一个策略,其余部分由现有的 ASP.NET Core 身份验证和授权组件处理。 是不是和上一章的限流是一个套路,都是 .NET
本身的功能,开箱即用。
配置授权策略,如下所示:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("customPolicy", policy => policy.RequireAuthenticatedUser());
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapReverseProxy();
要了解如何设置首选的身份验证类型,可以参阅身份验证文档
特殊值(内置策略):
除了自定义策略名称之外,还可以在路由的授权参数中指定两个特殊值: default
和 anonymous
。这是两个内置的策略名称,用于简化身份验证和授权配置。
- default 对应于用户已经通过身份验证的情况。如果用户已经登录,那么他们将满足
default
策略的要求。这通常用于需要用户已登录的资源或操作。 在路由的授权参数中指定值default
意味着路由将使用 AuthorizationOptions.DefaultPolicy 中定义的策略。该策略已预先配置为要求经过身份验证的用户。
示例用法:
app.MapGet("/default", () =>
{
return "hello";
}).RequireAuthorization();// 将具有指定名称的授权策略添加到终结点。空 代表使用 default 策略
上述的RequireAuthorization()
方法没给参数 默认就是用了 default
策略,已登录的用户才能通过验证。 而且还可以指定多个策略。他接收的是一个 params string[] policyNames
参数,你还可以添加其他策略。
YARP
中用法:
"Routes": {
"DefaultAuthRoute": {
"ClusterId": "cluster1",
// 此路由使用内置的默认授权策略,该策略要求经过身份验证的用户
"AuthorizationPolicy": "Default",
"Match": {
"Path": "/default"
}
}
}
- anonymous 对应于未经身份验证的用户,即匿名用户。如果用户没有登录,他们将满足
anonymous
策略的要求。这通常用于允许未经身份验证的用户访问资源或操作。 在路由的 authorization 参数中指定值anonymous
意味着无论应用程序中的任何其他配置(如 FallbackPolicy)如何,路由都不需要授权。
示例用法:
app.MapGet("/public", () =>
{
return "hello";
}).AllowAnonymous();
YARP 中用法:
"Routes": {
"AnonymousRoute": {
"ClusterId": "cluster1",
// 此路由使用内置的默认授权策略,该策略要求经过身份验证的用户
"AuthorizationPolicy": "Anonymous",
"Match": {
"Path": "/open/{*any}"
}
}
}
FallbackPolicy 回退策略
AuthorizationOptions.FallbackPolicy 用于处理未指定任何特定策略的路由。这是一个全局默认策略,如果路由没有指定特定策略,就会使用这个策略。通常情况下,FallbackPolicy
会采用默认策略,要求用户已通过身份验证。
示例用法:
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser() // 默认情况下,要求用户已通过身份验证. 可以提成你需要的验证
.Build();
});
YARP 中用法:
"Routes": {
"Other": {
// 由于以下路由未定义授权策略,因此使用回退策略
"ClusterId": "cluster1",
"Match": {
"Path": "{**catchall}"
}
}
}
Flowing Credentials 流动凭证
即使在代理中授权了请求后,目标服务器可能仍需要知道用户是谁(身份验证)以及允许他们执行的操作(授权)。如何传递该信息将取决于所使用的身份验证类型。
Cookie, bearer, API keys
这些身份验证类型已经在请求头中传递了它们的值,默认情况下这些值将流到目标服务器。该服务器仍然需要验证和解释这些值,这可能会造成一些双重工作(代理也校验,目标服务也校验)
Windows, Negotiate, NTLM, Kerbereos
这些身份验证类型通常绑定到特定连接。不支持将它们作为在 YARP
代理后面的目标服务器中对用户进行身份验证的方法(参见 #166。它们可用于对代理的传入请求进行身份验证,但该身份信息必须以另一种形式传达给目标服务器。它们还可用于向目标服务器验证代理,但只能作为代理自己的用户,不支持模拟客户端( YARP
无法代表客户端进行目标服务器的身份验证)
Client Certificates 客户端证书
客户端证书是一项 TLS 功能,作为连接的一部分进行协商。有关其他信息,请参阅这些文档。可以使用 ClientCert 转换将证书作为 HTTP 标头转发到目标服务器。
替换身份验证类型
像 Windows
这样不自然流到目标服务器的身份验证类型需要在代理中转换为其他形式。例如,可以使用用户信息创建 JWT
承载令牌,并在代理请求上进行设置。
可以使用自定义请求转换来执行这些交换(看起来又要加一章 请求转换 的篇章了 )。如果你有足够的兴趣,可以针对特定场景开发详细示例,反馈给 YARP
让他们了解您希望如何转换和流动身份信息的。
总结
本章我们介绍了 YARP
的认证和授权功能,概念比较多,此功能还是主要依赖于.NET 本身的认证和授权。如果有不了的可以先从微软文档学起,看起来相对会简单一些。本章建议结合示例代码一起看理解起来会比较方便,示例代码已上传GitHub
本章示例完整配置如下:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"DefaultAuthRoute": {
"ClusterId": "cluster1",
// 此路由使用内置的默认授权策略,该策略要求经过身份验证的用户
"AuthorizationPolicy": "Default",
"Match": {
"Path": "/default"
}
},
"ClaimsAuthRoute": {
"ClusterId": "cluster1",
// 自定义策略
"AuthorizationPolicy": "myPolicy",
"Match": {
"Path": "/custom/{*any}"
}
},
"AnonymousRoute": {
"ClusterId": "cluster1",
// 此路由使用内置的默认授权策略,该策略要求经过身份验证的用户
"AuthorizationPolicy": "Anonymous",
"Match": {
"Path": "/open/{*any}"
}
},
"Other": {
// 由于以下路由未定义授权策略,因此使用回退策略
// 程序中 设置为null,因此不需要身份验证或声明。
"ClusterId": "cluster1",
"Match": {
"Path": "{**catchall}"
}
}
},
"Clusters": {
"cluster1": {
"Destinations": {
"cluster1/destination1": {
"Address": "https://www.baidu.com/"
}
}
}
}
}
}
以上代码示例都是可以跑起来验证的,针对各种情况做了演示,有什么问题欢迎留言交流。
下篇文章我们继续 压缩 和 缓存 或者再补一篇 请求和响应转换。