如何在Web API的服务上下文中访问用户?

时间:2017-08-25 17:38:43

标签: asp.net asp.net-web-api asp.net-web-api2 asp.net-identity

如果您在控制器上下文中,则可以访问当前经过身份验证的用户。请参阅Get the current user, within an ApiController action, without passing the userID as a parameter等文章。

但是,如果我的控制器调用服务(同一个程序集),但在这里我没有控制器上下文。

实际获得经过身份验证的用户的最佳方式是什么?

1 个答案:

答案 0 :(得分:9)

您可以创建一个中间服务来提供该功能

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);
    }
}

当Identity Framework对用户进行身份验证时,将为当前上下文设置用户主体。

如果在IIS中托管,您可以使用HttpContext来访问用户,就像之前提供的示例一样。 MVC和Web API基本上类似于填充Controller.UserApiController.User

如果自托管有其他方法可以访问它。

事实是,一旦经过身份验证,用户就可以使用。将其封装在抽象之后,您可以在控制器之外的任何地方注入。

Asp.net Core引入了类似的IHttpContextAccessor,允许服务类访问控制器的当前HttpContext

public interface IHttpContextAccessor {
    HttpContext HttpContext { get; }
}