当前用户
在Web应用程序中获取已登录用户信息是非常常见的需求。当前用户指的是Web应用中与当前请求相关联的活跃用户。
ICurrentUser服务
ICurrentUser是获取当前活跃用户信息的主要服务。
示例:将ICurrentUser注入到服务中:
using System;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Users;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
private readonly ICurrentUser _currentUser;
public MyService(ICurrentUser currentUser)
{
_currentUser = currentUser;
}
public void Foo()
{
Guid? userId = _currentUser.Id;
}
}
}
常用基类已经将该服务作为基础属性注入。例如,您可以在应用服务中直接使用CurrentUser属性:
using System;
using Volo.Abp.Application.Services;
namespace AbpDemo
{
public class MyAppService : ApplicationService
{
public void Foo()
{
Guid? userId = CurrentUser.Id;
}
}
}
属性
以下是ICurrentUser接口的基础属性:
- IsAuthenticated (bool): 如果当前用户已登录(已认证)则返回
true。如果用户未登录,则Id和UserName将返回null - Id (Guid?): 当前用户的ID。如果用户未登录则返回
null - UserName (string): 当前用户的用户名。如果用户未登录则返回
null - TenantId (Guid?): 当前用户的租户ID,这对于 多租户 应用很有用。如果用户未分配租户则返回
null - Email (string): 当前用户的邮箱地址。如果用户未登录或未设置邮箱则返回
null - EmailVerified (bool): 如果当前用户的邮箱地址已验证则返回
true - PhoneNumber (string): 当前用户的电话号码。如果用户未登录或未设置电话号码则返回
null - PhoneNumberVerified (bool): 如果当前用户的电话号码已验证则返回
true - Roles (string[]): 当前用户的角色。返回当前用户角色名称的字符串数组
方法
ICurrentUser基于ICurrentPrincipalAccessor实现(参见下文),并通过声明(claims)工作。因此,上述所有属性实际上都是从当前认证用户的声明中获取的。
如果您有自定义声明或需要获取其他非标准声明类型,ICurrentUser提供了一些直接操作声明的方法:
- FindClaim: 获取指定名称的声明。如果未找到则返回
null - FindClaims: 获取所有指定名称的声明(允许存在多个同名声明值)
- GetAllClaims: 获取所有声明
- IsInRole: 检查当前用户是否属于指定角色的快捷方法
除了这些标准方法外,还有一些扩展方法:
- FindClaimValue: 获取指定名称声明的值,如果未找到则返回
null。它还有一个泛型重载,可以将值转换为特定类型 - GetId: 返回当前用户的ID。如果用户未登录,该方法会抛出异常(而不是返回
null)。仅在确定用户已认证的情况下使用此方法
认证与授权
ICurrentUser的工作方式与用户认证或授权方式无关。它可以与任何基于当前主体(principal)工作的认证系统无缝协作(参见下文)。
ICurrentPrincipalAccessor
ICurrentPrincipalAccessor是当需要获取当前用户主体时应由ABP框架和应用程序代码使用的服务。
对于Web应用程序,它获取当前HttpContext的User属性。对于非Web应用程序,它返回Thread.CurrentPrincipal。
通常您不需要使用这个底层的
ICurrentPrincipalAccessor服务,直接使用上文介绍的ICurrentUser即可。
基本用法
您可以注入ICurrentPrincipalAccessor并使用Principal属性获取当前主体:
public class MyService : ITransientDependency
{
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
public MyService(ICurrentPrincipalAccessor currentPrincipalAccessor)
{
_currentPrincipalAccessor = currentPrincipalAccessor;
}
public void Foo()
{
var allClaims = _currentPrincipalAccessor.Principal.Claims.ToList();
//...
}
}
更改当前主体
除非在高级场景中,否则通常不需要设置或更改当前主体。如果需要,可以使用ICurrentPrincipalAccessor的Change方法。该方法接受一个ClaimsPrincipal对象,并在某个范围内将其设置为"当前"主体。
示例:
public class MyAppService : ApplicationService
{
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
public MyAppService(ICurrentPrincipalAccessor currentPrincipalAccessor)
{
_currentPrincipalAccessor = currentPrincipalAccessor;
}
public void Foo()
{
var newPrincipal = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[]
{
new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()),
new Claim(AbpClaimTypes.UserName, "john"),
new Claim("Claim", "42")
}
)
);
using (_currentPrincipalAccessor.Change(newPrincipal))
{
var userName = CurrentUser.UserName; //返回"john"
//...
}
}
}
请始终在using语句中使用Change方法,这样在using作用域结束后会自动恢复原始值。
这可以作为一种在应用程序代码范围内模拟用户登录的方法,但请谨慎使用。
AbpClaimTypes
AbpClaimTypes是一个静态类,定义了ABP框架使用的标准声明名称:
UserName、UserId、Role和Email属性的默认值来自System.Security.Claims.ClaimTypes类,但您可以更改它们- 其他属性,如
EmailVerified、PhoneNumber、TenantId等,由ABP框架定义,尽可能遵循标准命名规范
建议使用此类的属性而不是魔术字符串来表示声明名称。
抠丁客


