如果您处于控制器上下文中,则可以访问当前经过身份验证的用户。以诸如在 ApiController 操作中获取当前用户之类的文章为例,而不将用户 ID 作为参数传递。
但是,如果我的控制器调用服务(同一程序集(,但此处我没有控制器上下文。
实际获取经过身份验证的用户的最佳方法是什么?
您可以创建一个中间服务来提供该功能
public interface IPrincipalProvider {
IPrincipal User { get; }
}
public class WebApiPrincipalProvider : IPrincipalProvider {
public IPrincipal User {
get {
return HttpContext.Current != null
? HttpContext.Current.User
: null;
}
}
}
并将其注入到依赖服务上下文中
public class MyService : IService {
private readonly IPrincipalProvider provider;
public MyService(IPrincipalProvider provider) {
this.provider = provider;
}
public MyModel MyServiceMethod() {
var currentUser = provider.User;
var name = currentUser.Identity.Name;
//...use user....
return model;
}
}
最后,确保抽象和实现在主应用程序的组成根中注册到 DI 容器中,以便当服务注入控制器时,它也能够访问当前请求的用户。
[Authorize]
public class MyController : ApiController {
public readonly IService service;
public MyController (IService service) {
this.service = service;
}
[HttpGet]
public IHttpActionResult MyGetActiom() {
var model = service.MyServiceMethod();
return Ok(model);
}
}
当标识框架对用户进行身份验证时,将为当前上下文设置用户主体。
如果托管在 IIS 中,则可以利用HttpContext
来访问用户,如前面提供的示例所示。MVC和Web API基本上做一些类似于填充Controller.User
和ApiController.User
的事情。
如果是自托管,还有其他方法可以访问它。
事实是,一旦通过身份验证,用户就可用。将其封装在抽象之后,您可以在控制器外部需要它的地方注入。
Asp.net Core 引入了类似的IHttpContextAccessor
,允许服务类访问控制器的当前HttpContext
public interface IHttpContextAccessor {
HttpContext HttpContext { get; }
}