ASP.NET MVC 5 - 身份。如何获取当前的ApplicationUser
Posted
技术标签:
【中文标题】ASP.NET MVC 5 - 身份。如何获取当前的ApplicationUser【英文标题】:ASP.NET MVC 5 - Identity. How to get current ApplicationUser 【发布时间】:2014-01-22 10:21:40 【问题描述】:我的项目中有一个 Article 实体,它具有名为 Author
的 ApplicationUser
属性。如何获取当前记录的ApplicationUser
的完整对象?在创建新文章时,我必须将Article
中的Author
属性设置为当前的ApplicationUser
。
在旧的会员机制中这很简单,但在新的身份方法中,我不知道该怎么做。
我试着这样做:
为身份扩展添加 using 语句:using Microsoft.AspNet.Identity;
然后我尝试获取当前用户:ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == User.Identity.GetUserId());
但我得到以下异常:
LINQ to Entities 无法识别方法“System.String GetUserId(System.Security.Principal.IIdentity)”方法,并且该方法无法转换为存储表达式。 来源=实体框架
【问题讨论】:
【参考方案1】:您应该不需要直接在数据库中查询当前的 ApplicationUser。
这引入了一个新的依赖关系,即为初学者提供额外的上下文,但未来用户数据库表会发生变化(过去 2 年中发生了 3 次),但 API 是一致的。例如,users
表在 Identity Framework 中现在称为 AspNetUsers
,并且几个主键字段的名称不断变化,因此几个答案中的代码将不再工作原样。
另一个问题是对数据库的底层 OWIN 访问将使用单独的上下文,因此来自单独 SQL 访问的更改可能会产生无效结果(例如,看不到对数据库所做的更改)。同样,解决方案是使用提供的 API,而不是尝试解决方法。
以 ASP.Net 身份访问当前用户对象的正确方法(截至目前)是:
var user = UserManager.FindById(User.Identity.GetUserId());
或者,如果您有异步操作,例如:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
FindById
要求您具有以下 using 语句,以便非异步 UserManager
方法可用(它们是 UserManager 的 扩展方法,因此如果您不包含此方法,您将只见FindByIdAsync
):
using Microsoft.AspNet.Identity;
如果您根本不在控制器中(例如,您正在使用 IOC 注入),则从以下位置完整检索用户 ID:
System.Web.HttpContext.Current.User.Identity.GetUserId();
如果您不在标准帐户控制器中,则需要将以下内容(作为示例)添加到您的控制器中:
1。添加这两个属性:
/// <summary>
/// Application DB context
/// </summary>
protected ApplicationDbContext ApplicationDbContext get; set;
/// <summary>
/// User manager - attached to application DB context
/// </summary>
protected UserManager<ApplicationUser> UserManager get; set;
2。在 Controller 的构造函数中添加:
this.ApplicationDbContext = new ApplicationDbContext();
this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));
2015 年 3 月更新
注意:身份框架的最新更新更改了用于身份验证的底层类之一。您现在可以从当前 HttpContent 的 Owin 上下文访问它。
ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
附录:
在 Azure 中使用 EF 和 Identity Framework 时,通过远程数据库连接(例如,本地主机测试到 Azure 数据库),您可能会随机遇到可怕的“错误:19 - 物理连接不可用”。由于原因隐藏在 Identity Framework 中,您无法在其中添加重试(或似乎缺少 .Include(x->someTable)
),因此您需要在项目中实现自定义 SqlAzureExecutionStrategy
。
【讨论】:
@TBA - 谢谢,我后来意识到这是一种扩展方法。需要添加 Microsoft.AspNet.Identity 使用 .再次感谢 找不到类型或命名空间 UserStore。我使用 Microsft.AspNet.Indentity 添加 @Zapnologica:这听起来像是一个新问题(建议你发布它)。您可以并行扩展ApplicationUser
类(特定于应用程序)和AspNetUsers
表,它们将提供任何新字段。再说一遍:不要直接打数据库! :)
@LifeH2O:FindById 返回的 ApplicationUser 是 your 类,带有 your 额外属性。请尝试一下。
等待您的新解决方法:P【参考方案2】:
我的错误,我不应该在 LINQ 查询中使用方法。
正确代码:
using Microsoft.AspNet.Identity;
string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
【讨论】:
User.Identiy.GetUserId 对我来说不存在。那是我自定义的方法吗?我只起身 User.Identity 没关系...您需要“使用 Microsoft.AspNet.Identity;”让那个方法在那里。 请注意,用户对象仅在控制器中可见。 您当然应该使用UserManager
方法而不是直接访问数据库吗?
@Josh Bjelovuk:当 API 可用时,切勿直接访问数据库。这为初学者引入了一个新的依赖关系,即为初学者提供额外的上下文,但未来用户数据库表会发生变化(过去 2 年中发生了 3 次),但 API 是一致的。【参考方案3】:
它在答案的 cmets 中,但没有人将此作为实际解决方案发布。
你只需要在顶部添加一个 using 语句:
using Microsoft.AspNet.Identity;
【讨论】:
我带着那个例外来到这里,我用那个using
解决了它。看到有 15,000 人访问了这个问题,我认为这是一个有用的答案:)
@TrueBlueAussie,尽管不是对 OPs 问题的直接回答,但我觉得提到 using 是一个非常有用的补充。
为了清楚起见,这是因为.GetUserId()
是一种扩展方法【参考方案4】:
Ellbar 的代码有效!您只需添加 using。
1 - using Microsoft.AspNet.Identity;
还有……Ellbar的代码:
2 - string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
使用此代码(在 currentUser
中),您可以处理连接用户的一般数据,如果您需要额外数据...请参阅 this link
【讨论】:
它可能“工作”,但肯定不建议绕过提供的 API 并直接访问数据库 如果您确实使用了该 API,则不需要额外的工作来获取额外的数据因为它已经在ApplicationUser
对象中
我同意!但是,之所以采用这种方式,是因为我今天已经有一个系统,在数据库中运行,我需要一个简单的解决方案来解决这个问题!当然,在早期的系统中,我会将对象放在适当的类和标识中。【参考方案5】:
从 ASP.NET Identity 3.0.0 开始,这已被重构为
//returns the userid claim value if present, otherwise returns null
User.GetUserId();
【讨论】:
【参考方案6】:ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
ApplicationUser currentUser = UserManager.FindById(User.Identity.GetUserId());
string ID = currentUser.Id;
string Email = currentUser.Email;
string Username = currentUser.UserName;
【讨论】:
【参考方案7】:对于 MVC 5,只需查看 WebApplication 模板脚手架中 ManageController 的 EnableTwoFactorAuthentication 方法,它就在那里完成:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EnableTwoFactorAuthentication()
await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
return RedirectToAction("Index", "Manage");
正如微软自己所建议的那样,答案就在那里:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
它将具有您在 ApplicationUser 类中定义的所有附加属性。
【讨论】:
已经涵盖。请检查是否尚未发布相同的答案(或对现有答案添加评论):)【参考方案8】:现在 asp.mvc 项目模板创建一个帐户控制器,以这种方式获取用户管理器:
HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()
以下对我有用:
ApplicationUser user = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(User.Identity.GetUserId());
【讨论】:
【参考方案9】:如果有人在web forms
中与Identity
用户合作,我会这样做:
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindById(User.Identity.GetUserId());
【讨论】:
【参考方案10】:我通过以下代码成功获得应用程序用户
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
ApplicationUser EmpUser = user;
【讨论】:
以上是关于ASP.NET MVC 5 - 身份。如何获取当前的ApplicationUser的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net MVC 5 身份验证与另一个 MVC 5 身份网站
如何在asp.net mvc 5身份中的授权属性中使用动态角色
如何使用 ASP.NET 5 MVC 6 保护 Web API