自定义asp.net身份存储-为什么HttpContext.Current有时为空 [英] custom asp.net identity store - why is HttpContext.Current empty at times

查看:136
本文介绍了自定义asp.net身份存储-为什么HttpContext.Current有时为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过遵循示例集此处.一切正常,除了:

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身份存储-为什么HttpContext.Current有时为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆