将 ClaimsPrincipal 从控制器传递到服务

Passing ClaimsPrincipal from Controller to Service

我是 .NET Core 的新手,但我正在尝试编写我的代码以尽可能遵守 SOLID 原则。

我有一个场景,在我的网站上注册的用户可能决定使用使用相同电子邮件的 Facebook 帐户登录;这会引发错误,因为我的用户 table 中的电子邮件字段是唯一的。

我的解决方案是创建某种关联 table Users_Facebook 就像这样...

在我注册用户的控制器中;为了获取 userId,我实施了一项服务(A. 检查现有用户的 user_facebook table 或(B. 根据电子邮件将 Facebook userId 与现有用户相关联。

            [Route("api/Users")]
            [HttpPost]
            public async Task<int> RegisterUser()
            {
                var userId = await userService.GetUserIdAsync(User);
                var email = User.Claims.First(e => e.Type == "emails").Value;
                var user = await _unitOfWork.Users.GetUserByIdAsync(userId);

                // Check contacts to see if one needs to be associated with a user
                var contact = await _unitOfWork.Contacts.GetContactByEmail(email);
                ...

服务片段:

            public async Task<string> GetUserIdAsync(ClaimsPrincipal authedUser)
            {
                var userId = authedUser.Claims.First(e => e.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
                var email = authedUser.Claims.First(e => e.Type == "emails").Value;

                var identityProvider = authedUser.HasClaim(e => e.Type == "http://schemas.microsoft.com/identity/claims/identityprovider") ?
                    authedUser.Claims.First(e => e.Type == "http://schemas.microsoft.com/identity/claims/identityprovider").Value : null;
                ...

我的问题是,这有什么问题吗?我将 ClaimsPrincipal 传递给我的服务可以吗?还是我打破了某种最佳实践?如果我完全离开了,有人可以建议一种更好的方法来做这样的事情吗?

提前致谢

就个人而言,我不会将 ClaimsPrincipal 传递到方法中。而是将 IHttpContextAccessor 传递到服务的构造函数中。这样它就可以通过这样做在 DI 容器中注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddHttpContextAccessor();
}

然后在您的服务中 class 像这样注入 IHttpContextAccessor

public class MyClass(IHttpContextAccessor context)
{
}

这意味着您可以从 class 中访问当前上下文,而无需通过方法传入。

要访问当前登录的用户,只需像这样访问它:

var username = Context.User.Identity.Name;