通过遵循示例集此处.一切正常,除了:
I've implemented a custom User Store for ASP.NET Identity by following the example set here. That all works fine, except for this:
我需要访问我的用户存储中有关当前登录用户的数据.通常,您可以通过访问
I need access to data about the currently logged in user in my user store. Normally, you'd access that by accessing
HttpContext.Current.User现在,一旦用户登录,如果该用户随后进入Manage控制器(例如尝试更改其密码),则当ASP.NET身份通过调用再次查找该用户时
Now, once auser has logged in, if he user then goes to the Manage controller (e.g. to try and change his/her password), when ASP.NET identity looks up the user again by calling
CustomUserManager.FindByIdAsync(string userId)HttpContext.Current完全为空(在呈现页面之前).那么,在这种情况下如何获取有关HttpContext的信息?该用户已正确登录,那么如何确定哪个用户已登录?
HttpContext.Current is empty altogether (that's prior to rendering the page). So, how do I get information about the HttpContext in this scenario? The user is properly logged in, so how do I figure out which user has been logged in?
@edit ..问题出在CustomUserStore ..有点问题
@edit.. the problem is in CustomUserStore.. here's a bit of it
public class CustomUserStore<TUser> : IUserStore<TUser>, IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserEmailStore<TUser>, IUserPhoneNumberStore<TUser>, IUserLockoutStore<TUser, string>, IUserTwoFactorStore<TUser, string>//, IQueryableUserStore<TUser> where TUser: CustomUser<string>, IUser<string> { string storageFile = @"c:\temp\aspnetusers.json"; List<TUser> users; public CustomUserStore() { if (File.Exists(storageFile)) { string contents = File.ReadAllText(storageFile); users = JsonConvert.DeserializeObject<List<TUser>>(contents); if (users == null) users = new List<TUser>(); } else users = new List<TUser>(); } #region IUserStore implementation public Task<TUser> FindByIdAsync(string userId) { string sessionId = HttpContext.Current?.Session?.SessionID; return Task.FromResult<TUser>(users.FirstOrDefault(u => u.Id == userId)); } public Task<TUser> FindByNameAsync(string userName) { string sessionId = HttpContext.Current?.Session?.SessionID; return Task.FromResult<TUser>(users.FirstOrDefault(u => string.Compare(u.UserName, userName, true) == 0)); } #endregion },它位于FindByAsync方法中,其中HttpContext.Current可以为空.
and it's in the FindByAsync method where HttpContext.Current can be empty.
创建模型时,它会在AccountController的Index方法中发生
It happens in the Index method of the AccountController when the model is created
var model = new IndexViewModel { HasPassword = HasPassword(), PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), Logins = await UserManager.GetLoginsAsync(userId), BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) };导致问题的原因是HasPassword方法中的FindById请求
And it's the FindById request in the HasPassword method that causes the problem
private bool HasPassword() { var user = UserManager.FindById(User.Identity.GetUserId()); if (user != null) { return user.PasswordHash != null; } return false; }对用户管理器的其他4个请求均具有填写的HttpContext.Current.因此,似乎是导致问题的原因是对UserManager的调用.
The other 4 requests to the user manager all have a filled out HttpContext.Current. So it appears that it's calls to UserManager that cause the issue.
推荐答案已经确定了问题的确切根源,因此很容易解决.
Having identified the exact source of the problem, it's easy enough to fix.
添加此异步方法以检查用户是否具有密码:
Add this async emthod to check if the user has a password:
private async Task<bool> HasPasswordAsync() { var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user != null) { return user.PasswordHash != null; } return false; }在Index方法中,使用新的异步方法
And in the Index method, use the new async methode
var model = new IndexViewModel { HasPassword = await HasPasswordAsync(), PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), Logins = await UserManager.GetLoginsAsync(userId), BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) };但是,为什么同步方法调用会中断事情呢?您会想象到同步调用将在HttpContext.Current应该可用的标准上下文中运行.
But, why does the synchronous method call break things? You'd imagine the sync call would run into the standard context where HttpContext.Current should be available.
在我的真实项目中,我有一个更自定义的用户存储,在这里我经常遇到此问题..我猜我需要检查是否包含对UserManager方法的更多同步访问.
I have a more custom User Store in my real project where I run into this problem a lot more frequently.. guess I need to check if contains a lot more synchronous access to UserManager methods.
更多推荐
自定义asp.net身份存储
发布评论