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。