在 ASP.NET Core 2.2 控制器上,我有以下内容:
var principal = this.User as ClaimsPrincipal;
var authenticated = this.User.Identity.IsAuthenticated;
var claims = this.User.Identities.FirstOrDefault().Claims;
var id = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
我能够检查用户是否是
authenticated
并获得claims
包括id
.
我怎么能在我没有
Controller
的this.User
之外做同样的事情?
注入
IHttpContextAccessor
接口到目标类。这将允许通过User
访问当前
HttpContext
这提供了一个机会,通过创建一个服务来提供您想要的信息(这是当前登录的用户)来抽象此功能
public interface IUserService {
ClaimsPrincipal GetUser();
}
public class UserService : IUserService {
private readonly IHttpContextAccessor accessor;
public UserService(IHttpContextAccessor accessor) {
this.accessor = accessor;
}
public ClaimsPrincipal GetUser() {
return accessor?.HttpContext?.User as ClaimsPrincipal;
}
}
您现在需要在
IHttpContextAccessor
中设置Startup.ConfigureServices
以便能够注入它:
services.AddHttpContextAccessor();
services.AddTransient<IUserService, UserService>();
并在需要的地方注入您的服务。
重要的是要注意
可能是null。只是因为 你有HttpContext
,不代表你会 居然总能搞定IHttpContextAccessor
。重要的是,代码在哪里 你正在使用这个must以某种方式在请求管道内或者HttpContext
将是 null.HttpContext
信用@ChrisPratt通过评论
您不想将
IHttpContextAccessor
接口注入非 Web 服务,因为这使它依赖于 ASP.NET Core,使其在 Web 请求的上下文之外无法使用。
相反,从您所在的控制器或页面中解析用户:
var user = await _userManager.FindByNameAsync(User.Identity!.Name);
// or by Id
var userId = User.FindFirst(Claims.UserId).Value;
var user = await _userManager.FindByIdAsync(userId);
现在你有一个
ApplicationUser
实例(或任何你命名你的身份用户实体),你可以将它传递给适当的服务:
await otherService.DoSomething(foo, bar, user);