我不确定我是否使用了正确的标题,但我想不出更好的方式来描述它。这可能更像是一个设计问题。
我有一个 Multi-Tenancy 数据库,其中一个用户可以属于一个或多个实体。我通过调用/token 端点使用他/她的凭据对用户进行身份验证。
收到 token 后,我调用自己的端点(使用 token )来获取该用户的可用实体列表,然后允许该用户在内存缓存中设置他的当前实体。然后,我在内存缓存中使用它来查找所有后续请求的实体/租户 ID,以了解用户在调用数据库时“登录”到哪个实体/租户。
理想情况下,我想消除对内存缓存的需求,以便通过将实体/租户 ID 作为声明包含在 token 中来使我的应用程序更加无状态,但我只在用户通过身份验证并选择他的之后才知道这个 ID/她的实体。我显然无法在 token 发布后更改或添加声明,但是否有替代设计来实现这种行为?
我考虑过可能为每个租户使用一个子域,但从技术上讲,这更难设置和维护。我还考虑过提示用户输入他/她希望登录的实体,作为带有凭据的自由文本,但这并不理想。
有没有人遇到过这个挑战?
最佳答案
我同意您的观点,即租户选择必须以无状态方式完成,以避免在基于 REST 的架构中进行有状态交互。缓存方法可能会导致许多陷阱,并引入对基于 session 的交互的强烈依赖。
我可以想到两个主要选项来使租户选择无状态:
基于 URI 的选择:您可以向 API 添加租户参数,在所有 Controller 之间共享。类似于此的映射:
api/{tenantId}/{controller}/{id}
可以让您以简单的客户端方式在租户之间切换。这可以使用基于约定的路由来完成:routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{tenantId}/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
或者基于属性的路由,在你的 Controller 上使用
RoutePrefixAttribute
:[RoutePrefix("api/{tenantId}/myentities")] public class EntityController : ApiController { [Route("")] public IHttpActionResult GetAllEntities(string tenantId) { //...
基于 header 的选择:您可以考虑添加自定义 HTTP header ,其中将包含有关所选租户的信息:例如
X-Tenant-Selection: TenantId
,然后你可以阅读这个 Header inside a customFilter
,或者在 Web API 之前执行的OwinMiddleware
中,并设置一个上下文变量(或者甚至是一个将持续当前请求的用户声明)以在您的 Controller 中使用。
当然,在这两种情况下,您都必须在返回数据之前验证当前用户是否可以访问所选租户。
坦率地说,我会排除将 tenantId 包含在访问 token 中的可能性,而且子域方法对我来说太复杂了。
关于c# - 具有 Multi-Tenancy 数据访问的 Web API 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36583626/