将ClaimsPrincipal从控制器传递到服务

时间:2019-06-10 11:42:15

标签: .net-core clean-architecture

我对.NET Core相当陌生,但是我试图编写尽可能遵循SOLID主体的代码。

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

我对此的解决方法是像这样创建某种关联表Users_Facebook ...

enter image description here

在我要注册用户的控制器中;要获取userId,我已经实现了一项服务(A.检查user_facebook表中是否存在现有用户,或(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传递给我的服务吗?还是我打破了某种最佳实践?如果我完全不在家,有人可以建议做这种事情的更好方法吗?

预先感谢

1 个答案:

答案 0 :(得分:1)

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

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

然后在服务类中像这样注入IHttpContextAccessor

public class MyClass(IHttpContextAccessor context)
{
}

这意味着您可以从类中访问当前上下文,而不必通过方法传递。

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

var username = Context.User.Identity.Name;