abp.runtime.sessionabp怎么用用

ABP理论学习之多租户 - 推酷
ABP理论学习之多租户
返回总目录
什么是多租户
ABP中的多租户
什么是多租户
维基百科:“软件
是指一种软件架构,在这种软件架构中,软件的
运行在服务器上并且为多个租户服务”。一个租户是一组共享该软件实例特定权限的用户。有了多租户架构,软件应用被设计成为每个租户提供一个
专用的实例包括该实例的数据的共享
,还可以共享配置,用户管理,租户自己的功能和非功能属性。多租户和多实例架构相比,多租户分离了代表不同的租户操作的多个实例。
多租户用于创建
Saas(Software as-a service)
应用(云处理)。有几种类型的多租户:
多部署-多数据库
这实际上不是多租户。但是,如果我们为
分开数据库的
客户(租户)运行该应用的一个实例,那么我们可以在单个服务器上为
提供服务。我们可以确定该应用的多个实例在相同的服务器环境不会相互
这个对于一个不是为多租户设计的
已存在应用
也是可能的。创建这么一个应用更容易,因为该应用不需要了解多租户。但这种方式存在安装,使用和维护问题。
单部署-多数据库
在这种情况下,我们可以在一个服务器上运行应用的
。对于每个登录用户,我们从
master database
中检测该用户的租户,并获得该租户的数据库信息(
连接字符串
)。然后我们可以将连接字符串存储到
一样的变量中,同时,使用这个
租户特定的
连接字符串执行所有的数据库操作。
某种程度上,这样的应用应该设计成多租户。但是大多数的应用都独立于多租户。这种方式也存在一些安装,使用和维护问题。我们应该为每个租户创建并维护一个
分离的数据库
单部署-单数据库
真实的多租户
架构:我们只将具有
单个数据库
单个服务器
上。在(RDBMS)每个表中,都存在一个
(或相似)字段,该字段用于分离每个租户之间的数据。
这种方法安装和维护都很简单,但唯独创建这么一个应用很难,因为我们必须要阻止一个租户读取或写入其他租户的数据。我们可以为每个数据库的读取(select)操作添加一个
TenantId过滤器
。而且,我们可以在每次写入的时候检查一下该实体是否和
当前的租户
相关。这是乏味而易于出错的,但ABP通过使用
自动的数据过滤
帮助我们处理这个事情。
如果我们有很多具有大量数据的租户,那么这种方法可能会有性能问题。我们可以使用关系型数据库的表分割特征或者将租户按组分到不同的服务器上。
ABP中的多租户
ABP提供了创建
单部署,单数据库,多租户
架构的基础设施。
开启多租户
多租户默认是关闭的。我们可以在模块的PreInitialize方法中开启,如下所示:
Configuration.MultiTenancy.IsEnabled =
租主vs租户
首先,我们应该定义多租户系统中的两个条目:
租主(Host)
:租主是单例的(只有一个租主)。租主会对创建和管理租户负责。因此,一个“
”比所有的租户等级更高,并独立于所有租户,同时还能控制他们。
租户(Tenant)
:租主的一个客户,具有自己的用户角色,权限,设置等。每个租户都可以完全独立于其他租户使用应用。一个多租户应用会有一个或多个租户。如果是一个CRM应用,那么不同的租户也有它们自己的账户,契约,产品和订单。因此,当我们说“**租户用户”的时候,意思就是一个租户拥有的用户。
ABP定义了一个获取当前
IAbpSession
接口。该接口用于多租户获取当前的租户id。因此,它可以基于当前的租户id过滤数据。ABP中有以下规则:
如果UserId和TenantId都是null,那么当前的用户没有登录到系统。因此,我们可以不知道当前用户是否是一个租主用户还是一个租户用户。在这种情况下,用户不能访问授权的内容。
如果UserId不是null,TenantId是null,那么当前用户是一个租主用户。
如果UserId不是null,TenantId也不是null,那么当前用户是租户用户。
更多关于session的信息请看后面的Session一节。
数据过滤器
当从数据库中检索实体时,我们必须添加一个TenantId过滤器来只获得当前的租户实体。当你为实体实现了
IMustHaveTenant和IMayHaveTenant
两个接口之一时,ABP会自动地完成数据过滤。
IMustHaveTenant接口
该接口通过定义
属性来区分不同租户的实体。一个实现了IMustHaveTenant的实体例子如下:
public class Product : Entity, IMustHaveTenant
public int TenantId { }
public string Name { }
//...其他属性
这样,ABP知道这是一个特定租户的实体,并且会自动地将一个租户的实体从其他实体中分离出来。
IMayHaveTenant接口
我们可能需要在租户和租户之间共享一个
。因此,一个实体可能会被一个租户或租主拥有。IMayHaveTenant接口也定义了
(类似于IMustHaveTenant),但在这种情况下是
。实现了IMayHaveTenant的一个实体例子:
public class Role : Entity, IMayHaveTenant
public int? TenantId { }
public string RoleName { }
//...其他属性
我们可能会使用相同的Role类来存储租主角色和租户角色。这种情况下,TenantId表明这是一个租户实体还是一个租主实体。null值表示这是一个
值表示这被一个
拥有,该租户的Id是
IMayHaveTenant不像IMustHaveTenant一样常用。比如,一个Product类可以不实现IMayHaveTenant接口,因为Product和实际的应用功能相关,和管理租户不相干。因此,要小心使用IMayHaveTenant接口,因为它更难维护租户和租主共享的代码。
一个租户用户不应该创建或编辑其他租户的实体。如果相关的数据过滤器开启了,那么ABP会检查该实体相对于数据库的改变。
想要获得更多关于数据过滤器的信息,请看后面关于数据过滤器的博客。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致ABP理论学习之授权(Authorization) - 推酷
ABP理论学习之授权(Authorization)
返回总目录
使用AbpAuthorize特性
使用IPermissionChecker
客户端(Javascript)
权限管理者
几乎所有的企业应用都在不同程度使用了授权。授权的目的在于检查是否允许用户在应用程序中执行特定的操作。ABP定义了一个
基于权限的
基础设施来实现授权。
关于IPermissionChecker
授权系统使用了
IPermissionChecker
来检查权限。虽然你可以用自己的方式实现该接口,但是它已完全实现在了
module-zero
项目中。如果没有实现该接口,那么系统会默认使用NullPermissionChecker将所有的权限授予给每个人。
一个唯一的权限是为需要授权的每个操作定义的。我们应该在使用权限之前定义一个权限。ABP的设计是模块化的,因此不同的模块可以有不同的权限。为了定义模块的权限,应该创建一个派生自
AuthorizationProvider(以下翻译为授权提供者)
的类。一个授权提供者的例子如下所示:
public class MyAuthorizationProvider : AuthorizationProvider
public override void SetPermissions(IPermissionDefinitionContext context)
var administration = context.CreatePermission(&Administration&);
var userManagement = administration.CreateChildPermission(&Administration.UserManagement&);
userManagement.CreateChildPermission(&Administration.UserManagement.CreateUser&);
var roleManagement = administration.CreateChildPermission(&Administration.RoleManagement&);
IPermissionDefinitionContext有创建和获取权限的方法。
一个权限定义了一些属性:
名字。最好为权限的名字定义一个const字符串而不是变量字符串。我们偏向使用“.”符号用于有层次的名字,但这不是强制的。你可以设置任何你喜欢的名字,唯一的一点是保证它必须是唯一的。
DisplayName:
用于以后在UI上显示权限的本地化字符串。
Description:
用于以后在UI上显示权限定义的本地化字符串。
IsGrantedByDefault:
表示该权限是否授予给所有登录的用户,除非该权限显示禁止未授予给用户。该值一般默认为false。
MultiTenancySides:
对于多租户应用,租户或者租主可以使用同一个权限。这是一个
枚举,因此一个权限可以用于租户和租主。
dependedFeature:
可以用于声明一个功能的依赖。因此,只有功能依赖满足了,该权限才会被授予。
一个权限可以有父权限和子权限。虽然这不会影响权限检查,但是在UI上组合权限有所帮助。
当创建了授权提供者之后,我们应该在模块的PreIntialize方法中注册它:
Configuration.Authorization.Providers.Add&MyAuthorizationProvider&();
因为授权提供者会自动地注册到依赖注入系统中,所以,授权提供者通过一些其他资源,可以注入任何依赖(比如仓储)来生成权限定义。
使用AbpAuthorize特性
AbpAuthorize(MVC控制器是AbpMvcAuthorize,Web API控制器是AbpApiAuthorize)是最简单也是最普通的检查权限的方式。思考一下下面的应用服务方法:
[AbpAuthorize(&Administration.UserManagement.CreateUser&)]
public void CreateUser(CreateUserInput input)
//如果一个用户没有被授予 &Administration.UserManagement.CreateUser& 权限,那么ta就不能执行此方法
AbpAuthorize特性也会检查当前的用户是否已经登录(使用
)。因此,如果我们为一个方法声明了AbpAuthorize,它至少会检查登录情况:
[AbpAuthorize]
public void SomeMethod(SomeMethodInput input)
//如果用户没有登录,那么ta就不能执行此方法
AbpAuthorize特性需要注意的地方
ABP对于授权使用了强大的动态方法拦截(interception)。因此,使用AbpAuthorize特性有一些限制:
不能用于私有方法。
不能用于静态方法。
不能用于非注入类的方法(我们必须要使用依赖注入)。
可以用于任何
方法,如果该方法是通过接口调用的(比如应用服务通过接口使用)。
方法应该是
的,如果它是从类的引用直接调用的(比如ASP.Net MVC或者Web API的控制器)。
如果方法是
的,那么它应该是
注意:AbpAuthorize特性有三个:
在应用服务中(应用层),我们使用
Abp.Authorization.AbpAuthorize
在MVC控制器中(Web层),我们使用
Abp.Web.Mvc.Authorization.AbpMvcAuthorize
在ASP.NET Web API中,我们使用
Abp.WebApi.Authorization.AbpApiAuthorize
这个差异来自继承。在MVC端,派生自MVC自己的Authorize类。在Web API端,它派生自Web API的Authorize类。因此,它已经很好地集成到了MVC和Web API。但是在应用层,它完全是ABP自己的实现而没有扩展任何类。
使用IPermissionChecker
虽然AbpAuthorize特性对于大多数情况相当够用了,但是肯定存在我们会在一个方法体内检查权限的情况。我们可以注入并使用
IPermissionChecker
,如下面的例子所示:
public void CreateUser(CreateOrUpdateUserInput input)
if (!PermissionChecker.IsGranted(&Administration.UserManagement.CreateUser&))
throw new AbpAuthorizationException(&You are not authorized to create user!&);
//如果一个用户没有&Administration.UserManagement.CreateUser& 权限,那么ta不能到达该点。
当然,你可以编写任何逻辑代码,因为
仅仅返回true或者false(也有Async版本)。如果你只是检查一个权限然后抛出一个如上所示的异常,那么你可以使用
public void CreateUser(CreateOrUpdateUserInput input)
PermissionChecker.Authorize(&Administration.UserManagement.CreateUser&);
//如果一个用户没有&Administration.UserManagement.CreateUser& 权限,那么ta不能到达该点。
因为授权一般在应用层实现,所以
ApplicationService
基类注入并定义了PermissionChecker属性。这样,权限检查者不需要在应用服务类中注入就可以使用了。
视图基类定义了IsGranted方法来检查当前用户是否具有权限。因此,我们可以有条件地渲染该视图。例子:
@if (IsGranted(&Administration.UserManagement.CreateUser&))
&button id=&CreateNewUserButton& class=&btn btn-primary&&&i class=&fa fa-plus&&&/i& @L(&CreateNewUser&)&/button&
客户端(Javascript)
在客户端,我们可以使用定义在
命名空间下的API。在大多数情况,我们需要检查当前的用户是否具有特定的权限(使用权限名字)。例子:
abp.auth.hasPermission('Administration.UserManagement.CreateUser');
你也可以使用
abp.auth.grantedPermissions
来获得所有授权的权限或者使用
abp.auth.allPermissions
来所有应用中可用的权限名。
权限管理者
我们可能需要定义权限。这时可以注入并使用
IPermissionManager
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致基于DDD的现代ASP.NET开发框架--ABP系列之7、ABP&Session管理
ABP是&ASP.NET Boilerplate Project (ASP.NET样板项目)&的简称。
ABP的官方网站:
ABP在Github上的开源项目:
如果一个应用程序需要登录,则它必须知道当前用户执行了什么操作。因此ASP.NET在展示层提供了一套自己的SESSION会话对象,而ABP则提供了一个可以在任何地方 获取当前用户和租户的IAbpSession接口。
关于IAbpSession
需要获取会话信息则必须实现IAbpSession接口。虽然你可以用自己的方式去实现它(IAbpSession),但是它在module-zero项目中已经有了完整的实现。
注入Session
IAbpSession通常是以属性注入的方式存在于需要它的类中,不需要获取会话信息的类中则不需要它。如果我们使用属性注入方式,我们可以用 NullAbpSession.Instance作为默认值来初始化它(IAbpSession),如下所示:
public class MyClass : ITransientDependency
public IAbpSession AbpSession { get; set; }
public MyClass()
AbpSession = NullAbpSession.I
public void MyMethod()
var currentUserId = AbpSession.UserId;
由于授权是应用层的任务,因此我们应该在应用层和应用层的上一层使用IAbpSession(我们不在领域层使用IAbpSession是很正常的)。
ApplicationService, AbpController 和 AbpApiController 这3个基类已经注入了AbpSession属性,因此在Application Service的实例方法中,能直接使用AbpSession属性。
使用Session属性
AbpSession定义的一些关键属性:
UserId: 当前用户的标识ID,如果没有当前用户则为null.如果需要授权访问则它不可能为空。
TenantId: 当前租户的标识ID,如果没有当前租户则为null。
MultiTenancySide: 可能是Host或Tenant。
UserId和TenantId是可以为null的。当然也提供了不为空时获取数据的 GetUserId()和GetTenantId() 方法 。当你确定有当前用户时,你可以使用GetUserId()方法。如果当前用户为空,使用该方法则会抛出一个异常。GetTenantId()的使用方式和GetUserId()类似。
ABP框架中的AbpSession, 并没有使用到System.Web.HttpSessionStateBase, 而是自己定义了一个Abp.Runtime.Session.IAbpSession接口, 并在Zero模块中通过AspNet.Identity组件实现了AbpSession对象的存值、取值。 所以即使Web服务重启,也不会丢失Session状态。
在我自己的项目中, Session对象只有UserId、TenantId、MultiTenancySide这几个属性是不够用的,我扩充了几个属性和方法,使用起来非常方便。有这个需求的朋友,欢迎加入QQ群与我交流。
希望更多国内的架构师能关注到ABP这个项目,也许这其中有能帮助到您的地方,也许有您的参与,这个项目可以发展得更好。
欢迎加ABP架构设计交流QQ群:
阅读(...) 评论()

我要回帖

更多关于 abp session 的文章

 

随机推荐