【问题标题】:Pass UserID with HttpContext.Session to different Controller将带有 HttpContext.Session 的 UserID 传递给不同的控制器
【发布时间】:2020-06-19 16:48:08
【问题描述】:

我已经搜索过类似的问题,但由于一些语法发生了变化,我还没有找到我正在寻找的答案。

我正在尝试从 Login/HomeController 传递用户 ID,因此应用程序的所有控制器/视图都可以访问它。登录目前是硬编码的,因为我现在只是想传递一个值。

Session["key"] 不起作用,HttpContext.Current 也不起作用,它甚至在最新的 MVC 版本中都不存在。 在 HomeController 本身中,我可以使用 HttpContext.Session.SetString(Key, "string") 添加值 但我不知道如何在其他控制器/视图中访问它。

我找到了IHttpContextAccessor,但由于我必须在我想使用它的所有类中的每个构造函数中将它作为参数传递,而且我已经传递了一个缓存参数,这似乎有点“矫枉过正”

有没有更好的方法将 UserID 传递给所有控制器?

这是我的startup.cs

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddSingleton<ILocationContainer, LocationContainer>();
            services.AddDistributedMemoryCache();
            services.AddHttpContextAccessor();
            services.AddSession(options => {
                options.IdleTimeout = TimeSpan.FromMinutes(20);
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
            });
            services.AddMvc();

        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {


            app.UseAuthorization();

            app.UseSession();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

这是我在控制器中的代码

public IActionResult Login()
        {
            HttpContext.Session.SetString(UserAccount, "blabla");
            HttpContext.Session.SetString(UserRole, "admin");
            return RedirectToAction("Index", "Home");

        }

【问题讨论】:

  • 这正是您不需要传递的那种数据。如果您使用身份,只需在需要时使用可用的机制来获取此数据。

标签: c# asp.net-core model-view-controller


【解决方案1】:

直到 ASP.NET Core 1.0 RC1:它是来自 System.Security.Claims 命名空间的 User.GetUserId()。

从 ASP.NET Core 1.0 RC2 开始:您现在必须使用 UserManager

在控制器中你需要这样的东西:

public class YourControllerNameController : Controller
{
   private readonly UserManager<ApplicationUser> _userManager;

   public YourControllerNameController(UserManager<ApplicationUser> userManager)
   {
    _userManager = userManager;
   }

public async Task<IActionResult> YourMethodName()
 {
    var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) // will give the user's userId
    var userName =  User.FindFirstValue(ClaimTypes.Name) // will give the user's userName

    ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
    string userEmail = applicationUser?.Email; // will give the user's Email
 }
}

这方面的信息很多 你必须阅读这个: https://stackoverflow.com/a/52135130

【讨论】:

  • 感谢您的帮助,我现在已经用 IHttpContextAccessor 解决了,因为我们不能真正使用 Identity 类,请参阅上面的评论
【解决方案2】:

您可以创建一个基本控制器并在您需要用户信息的每个控制器中继承。

  public class CustomBaseController : ControllerBase
  {
            public UserInfo UserInfo
            {
                Id = User.FindFirstValue(ClaimTypes.NameIdentifier),
                Name = User.FindFirstValue(ClaimTypes.Name),
                PhoneNumber = User.FindFirstValue("PhoneNumber")    
            };
  }

public class UserController : CustomBaseController
{
    public IActionResult Login()
    {
        var user = _context.User.Find(UserInfo.Id);

        // some code
    }
}

【讨论】:

  • 感谢您的帮助,不幸的是,我们不应该使用 EF 框架甚至任何类型的数据库(我们使用 JSON 导出/导入,不要问我为什么,大学......)和所以使用 Identity 会非常复杂。我现在已经通过使用 IHttpContextAccessor 解决了这个问题,尽管 Identity 会使编码变得容易得多,尤其是在涉及 UserRoles 时...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多