2.2 ABP公共结构 - 会话管理
2.2.1 简介
ABP提供了 IAbpSession 接口获取当前用户以及租户信息,而不是使用ASP.NET的Session。IAbpSession也被集成且使用在ABP其他模块中,例如:设置管理,权限认证。
2.2.2 注入会话
IAbpSession通常是以属性注入的方式存在于需要它的类中,不需要获取会话信息的类中则不需要它。如果我们使用属性注入方式,我们可以用NullAbpSession.Instance作为默认值来初始化它(IAbpSession),如下所示:
public class MyClass : ITransientDependency
{
public IAbpSession AbpSession { get; set; }
public MyClass()
{
AbpSession = NullAbpSession.Instance;
}
public void MyMethod()
{
var currentUserId = AbpSession.UserId;
//...
}
}
由于授权是应用层的任务,因此我们应该在应用层和应用层的上一层使用IAbpSession(我们不在领域层使用IAbpSession是很正常的)。
ApplicationService, AbpController 和 AbpApiController 这3个基类已经注入了AbpSession属性,因此在Application Service的实例方法中,能直接使用AbpSession属性。
2.2.3 使用会话属性
AbpSession定义的一些关键属性:
UserId: 当前用户的标识ID,如果没有当前用户则为null。如果调用的代码是已授权,那么它不可能为空。
TenantId: 当前租户的标识ID,如果没有当前租户则为null(如果用户没有登录或者他是一个Host用户)。
ImpersonatorUserId: 模拟用户的标识ID,如果当前会话被其他用户模拟登录。如果不是一个模拟登录,那么该值为空。
ImpersonatorTenantId: 模拟用户租户的标识ID,如果当前会话被其他用户模拟登录。如果不是一个模拟登录,那么该值为空。
MultiTenancySide: 可能是Host或Tenant。
UserId和TenantId是可空类型。当然也提供了不为空时获取数据的 GetUserId() 和 GetTenantId() 方法 。当你确定有当前用户时,你可以使用GetUserId()方法。
如果当前用户为空,使用该方法则会抛出一个异常。GetTenantId()的使用方式和GetUserId()类似。
模拟属性不像其它通用属性一样用于审计日志。
ClaimsAbpSession
在Abp中 ClaimsAbpSession 实现了 IAbpSession 接口。它从当前用户的 princical 的 claims 中取得session属性(除了 MultiTenancySide)。对于一个基于Form认证的cookie,它会从cookie中取得session。因此,它很好的集成了ASP.NET的认证机制。
2.2.4 覆盖当前session值
在某种特别的情况下,你可能想在某个限定的作用域下改变/覆盖会话值。那么你可以使用 IAbpSession.Use 方法,如下所示:
public class MyService
{
private readonly IAbpSession _session;
public MyService(IAbpSession session)
{
_session = session;
}
public void Test()
{
using (_session.Use(42, null))
{
var tenantId = _session.TenantId; //42
var userId = _session.UserId; //null
}
}
}
Use 方法返回了一个 IDisposable 对象,并且该对象 必须是可释放的 。 一旦该对象被释放了,Session值会自动的还原为之前使用的值。
警告
你应该像上面一样使用它,在using语法糖中使用。否则,你会得到意想不到的session值。你可以嵌套使Use,它会按你预期的工作。
2.2.5 User Identifier
你可以使用 ToUserIdentifier() 扩展方法从IAbpSession创建一个UserIdentifier对象。因为UserIdentifier被大多数API使用,所以使用该方法可以很方便的为当前用户创建一个UserIdentifier。