【问题标题】:Keeping current user object in memory将当前用户对象保存在内存中
【发布时间】:2014-06-10 10:45:53
【问题描述】:

WinForms 应用程序中,我想在整个应用程序生命周期中将当前登录的用户保留在内存中。这样在后续的用户操作中,我可以检查用户的权限。另一种选择是将用户信息存储在本地的文本文件中,但这似乎不安全。

用户登录验证码

private void ValidateUser()
{
    var hashEntered = Encryption.GetHash(_View.UserID, _View.Password); //hash of the salted password entered by user.

    var User = _DataService.GetUser(_View.UserID); //user trying to log in

    if (user != null)
    {
        var hashInDB = user.PassWord;

        if (hashEntered != hashInDB)
        {
            MessageBox.Show("Invalid password");
        }
        else
        {
            _MainView.show(); 
        }
    }
    else
    {
        MessageBox.Show("Invalid user name");
    }
}

所以对于 MainView,当前登录的用户应该是可用的。

如何将当前用户对象保留在内存中直到程序退出?

【问题讨论】:

  • 如果我理解正确,您希望保存用户对象,然后检查该对象的权限。当后端更改用户权限时会发生什么?这是“检查时间到使用时间”问题的经典示例。 en.wikipedia.org/wiki/Time_of_check_to_time_of_use
  • 我应该提到权限信息要保存在内存中。只有用户信息(至少是UserID)

标签: c# .net winforms memory mvp


【解决方案1】:

我建议单身。

public class UserSession{
    private static volatile User currentUser;
    private static object syncRoot = new Object();

    private UserSession() {}

    public static User GetUser(){
        if (currentUser == null) throw new Exception("Not logged in.");
        return currentUser;
    }

    public static void Login(User user){
        if (currentUser != null) throw new Exception("Already logged in");
        lock(syncRoot){
            currentUser = user;
        }
    }

    public static void Logout(){
        lock(syncRoot){
            currentUser = null;
        }
    }
}

【讨论】:

  • 如果你要使用lock,你应该lock所有对currentUser的引用。
【解决方案2】:

您可以将用户数据存储在IPrincipal 类型的System.Threading.Thread.CurrentPrincipal 中,它还有一个名为Identity 的属性(其类型为IIdentity)。这两者之间的区别在于,您只需将用户的安全相关数据(假设权限或角色)存储在主体中,而将其他数据存储在身份中。您可以使用 Microsoft 现有的这两个接口的实现,也可以自己构建它们。这是一个例子

class CustomPrincipal : IPrincipal
{
    public IEnumerable<string> Roles { get; set; }

    public IIdentity Identity { get; set; }

    public bool IsInRole(string role)
        {
            // check user for appropriate roles
            return false;
        }
}

class CustomIdentity : IIdentity
{
    public int UserId { get; set; }

    public string AuthenticationType { get; set; }

    public bool IsAuthenticated
    {
        get { return !string.IsNullOrWhiteSpace(Name); }
    }

    public string Name { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        CustomIdentity identity = new CustomIdentity
        {
            UserId = 1,
            Name = "user1"
        };

        CustomPrincipal principal = new CustomPrincipal
        {
            Identity = identity,
            Roles = new List<string> { "admin", "superAdmin" }
        };

        System.Threading.Thread.CurrentPrincipal = principal;
    }
}

Principal 是ExecutionContext 的一部分,所以它会从一个线程复制到另一个线程。因此,即使您要启动一个新线程或任务或任何试图获取 Principal 的异步作业,它也会在那里

您将使用此代码而不是检索用户主体

System.Threading.Thread.CurrentPrincipal as CustomPrincipal

这是获取用户身份

System.Threading.Thread.CurrentPrincipal.Identity as CustomIdentity

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多