【问题标题】:How to get User ID inside a separate assembly如何在单独的程序集中获取用户 ID
【发布时间】:2022-03-23 08:01:45
【问题描述】:

我正在开发一个有两个项目的应用程序:

  1. 核心 - 使用存储库模式和域驱动设计来容纳数据访问层
  2. UI - 使用 ASP.Net MVC。目前,我可以通过 User 属性在 UI 控制器中获取当前登录用户的信息(id、姓名等),如下所示:

    using Microsoft.AspNet.Identity;
    
    public class ExamController : Controller
    {
       IExaminationRepository _repository;
    
       public ExamController()
       {
         _repository = RepositoryFactory.Get<IExaminationRepository>();
       }
    
       [HttpPost]
       [Authorize(Roles = "Examiner")]
       public ActionResult Create(ExamViewModel viewModel)
       {
          try
          {
            ExaminationDomain domain = Mapper.Map<ExamViewModel, ExaminationDomain>(viewModel);
    
            //TODO: Move this to the repository
            domain.AuthorId = User.Identity.GetUserId();
    
            _repository.Add(domain);
    
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
      }
    }
    

我想将这一行:domain.AuthorId = User.Identity.GetUserId(); 移动到我的存储库具体实现中,如下所示:

using Microsoft.AspNet.Identity;
using System.Security.Principal;

internal class ExaminationRepository
{
    public DBEntities context;
    public IPrincipal User;

    public ExaminationRepository(DBEntities context)
    {
        this.context = context;
        //I'd like to instantiate User property here:
        this.User = "not sure what to instantiate with";
    }

    public void Add(ExaminationDomain domain)
    {
        Examination newExam = Mapper.Map<ExaminationDomain, Examination>(domain);

        newExam.AuthorId = User.Identity.GetUserId();

        newExam.CreatedBy = User.Identity.Name;

        newExam.CreatedDate = DateTime.Now;

        context.Examinations.Add(newExam);

        context.SaveChanges();

    }

但我不确定在构造函数中将 User 属性实例化为什么。我已经阅读了一些使用 WindowsIdentity.GetCurrent().User 而不是创建用户属性的建议,但这不包含用户 ID,仅包含用户名。

关于获取用户信息还有其他建议吗?

非常感谢您对此提供的帮助..

谢谢,

【问题讨论】:

  • @PW..不,我想它不可能在 Reposiroty 类中检索到该用户名值

标签: c# asp.net-mvc repository-pattern


【解决方案1】:

我会使用自定义管理器将您的存储库与 httpcontext 分离。例如我有一个名为 IAUthenticationManager 的接口

public interface IAUthenticationManager
{
   string CurrentUserId();

   bool HasCurrentUserRole(string roleName),
}

易于测试且完全解耦。

【讨论】:

    【解决方案2】:

    这并不容易,因为存储库可以在许多不同的上下文中使用,即使是没有设置用户的上下文。如果您在构造函数中创建具体依赖项,您的存储库将不再是独立的数据提供者。

    例如引用

    HttpContext.Current.User.Identity
    

    直接会创建对 Web 上下文的依赖项,并且存储库将无法在非 Web 上下文中使用。

    你能做的最好的就是让存储库客户端提供这个:

    public void Add(ExaminationDomain domain, IPrincipal principal)
    {
        Examination newExam = Mapper.Map<ExaminationDomain, Examination>(domain);
    
        newExam.AuthorId = principal.Identity.GetUserId();
        newExam.CreatedBy = principal.Identity.Name;
        newExam.CreatedDate = DateTime.Now;
    
        context.Examinations.Add(newExam);
    
        context.SaveChanges();
    }
    

    或(可能)

    public ExaminationRepository(DBEntities context, IPrincipal user)
    {
        this.context = context;
        this.user    = user;
    }
    

    如果您告诉容器如何解决依赖关系,IoC 容器仍然可以正确解决后一种情况。

    在网络环境中,您可以将容器设置为将其解析为HttpContext.Current.User。 在非 Web 上下文中,您可以将容器设置为将其解析为 WindowsIdentity.GetCurrent().User

    【讨论】:

      【解决方案3】:

      使用 HttpContext 类女巫是一个单例类: 首先向 Microsoft.AspNet.Identity 添加一个 using; 然后你可以做这样的事情:

      HttpContext.Current.User.Identity.GetUserId();
      

      由于 GetUserId 是一种扩展方法,因此您可以引用 Microsoft.AspNet.Identity

      但是,如果您需要在应用程序的多个位置访问用户信息,我建议您拥有一个包含您需要的属性的包装类,并在用户登录时将其实例化,然后将其存储在会话变量中,这样您有两个好处:

      1- 你不需要查询 db 来获取用户名、电子邮件等。关于整个应用程序中的每个用户信息使用情况。

      2- 您的存储库不需要以 aspnet 身份存在的程序集。

      【讨论】:

        【解决方案4】:

        你需要用当前线程的身份信息实例化this.User:

        this.User = System.Threading.Thread.CurrentPrincipal;
        var currentIdentity = (System.Security.Claims.ClaimsIdentity)User.Identity;
        var userId = currentIdentity.Claims
            .Where(p => p.Type.EndsWith("nameidentifier")).Single().Value;
        

        请注意,CurrentPrincipal.Identity 的类型是 IIdentity。您可以将其强制转换为 System.Security.Claims.ClaimsIdentity,其中包含一个名为 Claims 的属性。此属性包含您的所有声明,包括用户 ID 和第 3 方令牌(例如 Facebook 令牌)。

        要检索 UserId,请查找 Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" 的声明

        【讨论】:

          猜你喜欢
          • 2020-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-16
          • 2021-05-11
          • 2012-04-19
          相关资源
          最近更新 更多