【问题标题】:Will the static public variables in my app get shared with other users in the same app?我的应用程序中的静态公共变量会与同一应用程序中的其他用户共享吗?
【发布时间】:2010-11-11 19:47:37
【问题描述】:

出于我不想讨论的原因,我需要为我的应用创建一个自定义身份验证系统。我只是在查看系统,并且怀疑我的解决方案是否是线程安全的。我的目标是创建一个解决方案,允许我的应用程序一次对用户进行身份验证,并且用户身份验证信息将由所有使用的母版页、页面、类、用户控件等共享。 (但不会在用户之间共享相同的信息)

这是我的设置:

PageHttpModule.cs - 作为 httpModule 添加到 web.config。

public class PageHttpModule : IHttpModule
{
    public void Init(HttpApplication app)
    {
        app.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
    }

    public void OnAuthenticateRequest(Object s, EventArgs e)
    {
         CurrentUser.Initialize();
    }

    public void Dispose() { }
}

CurrentUser.cs

public static class CurrentUser
{
  public static bool IsAuthenticated { get; private set; }
  public static string Email {get; set;}
  public static string RealName {get; set;
  public static string UserId {get; set;}

    public static void Initialize()
    {
        CurrentUser.AuthenticateUser();
    }


    Note: this is a scaled down version of my authentication code.

    public static void AuthenticateUser()
    {
        UserAuthentication user = new UserAuthentication();
        user.AuthenticateUser();

        if (user.IsAuthenticated)
        {
            CurrentUser.IsAuthenticated = true;
            CurrentUser.UserId = user.UserId;
            CurrentUser.Email = user.Email;
            CurrentUser.RealName = user.RealName;
        }
     }
}

UserAuthentication.cs

public class UserAuthentication
{

    public string Email { get; set; }
    public string RealName { get; set; }
    public string UserId { get; set; }
    public bool IsAuthenticated { get; private set; }

    public UserAuthentication()
    {
        IsAuthenticated = false;
        Email = String.Empty;
        RealName = String.Empty;
        UserId = String.Empty;
    }

    public void AuthenticateUser()
    {

        //do some logic here.. if the user is ok then 
        IsAuthenticated = true
        Email = address from db
        UserId = userid from db;
        Realname = name from db;
   }
}

我已经在 3 种不同的浏览器之间进行了测试,似乎运行良好,但我仍在学习,不想犯大错。

如果我的逻辑完全错误,那我应该怎么做,这样我就不必直接在每个页面上进行用户查找?

【问题讨论】:

  • 我喜欢以“我要做这件完全疯狂的事情而且我不会讨论为什么”开头的问题。
  • 我在经典 ASP 中有一个现有的身份验证方案,我需要镜像... :)

标签: c# .net asp.net static class-design


【解决方案1】:

不,这不是线程安全的。对于存在于不同进程或 AppDomain 中的应用程序实例,这会很好。但是,如果您的 ASP.NET 服务器要使用线程同时处理多个请求,那么如果两个人同时尝试使用该应用程序,您将会产生一些非常糟糕的副作用。

【讨论】:

  • 有什么想法可以在不完全报废的情况下修复它吗?
  • 您可以不使用静态类,而是返回 UserAuthentication 对象并将其存储在来自 PageHttpModule.OnAuthenticateRequestHttpContext.Current.Items 上。
  • 可能是一个可行的解决方案。理想情况下,我希望页面上的所有现有 CurrentUser.IsAuthenticated 等都能正常工作。也许我要求太多了……
  • 我不确定你能做到这一点,除非你能找到一种方法在每次使用的范围内创建一些名为 CurrentUser 的变量/字段/属性。
【解决方案2】:

Init方法中,HttpApplication参数描述为:

一个 HttpApplication 提供对 ASP.NET 应用程序中所有应用程序对象通用的方法、属性和事件的访问

这里的关键是,在应用的生命周期中存在一个PageHttpModule,并且应用生命周期中存在的所有静态对象都将共享这些变量。

但是...CurrentUser 的生命周期仅在OnAuthenticateRequest 事件的范围内,除非其他一些引用使对象保持活动状态。如果它是PageHttpModule 成员级变量,那么您会立即发现问题。但是,在您的情况下,只要您没有收到多个同时处理的OnAuthenticateRequest 呼叫,您就可以正常工作。

您的问题的答案是否定的,您不能保证是线程安全的。如果两个身份验证请求同时进入,则不能保证一个事件在另一个事件开始之前完成,在这种情况下,第二个用户可能会显示为已通过身份验证,而实际上它是第一个登录的用户。


更新
我认为部分问题来自对AuthenticateRequest 的误解...到调用此事件时,用户已经通过Windows 或Forms 身份验证...您只是收到通知它已经发生.事实上,User.Identity.IsAuthenticated 属性已经被设置(我相信即使用户身份验证失败也会触发此事件,但我不会在不仔细检查的情况下发誓)。

如果我了解您的需求,那么您实际上是在尝试编写自己的自定义会员提供程序。如果您采用这种方法,您将获得内置身份验证的所有好处...所有与身份验证相关的标准属性都将被设置和访问,并且将以您想要的方式与用户会话隔离。

编写自定义提供程序不是一件小事,但它是可行的,并且您应该能够重用您当前用于类的大量逻辑和代码。

尝试完全重写身份验证机制将是一个痛苦而复杂的过程。

部分链接:
http://www.devx.com/asp/Article/29256/0/page/3
http://www.codeproject.com/KB/aspnet/WSSecurityProvider.aspx
http://msdn.microsoft.com/en-us/library/f1kyba5e%28v=VS.90%29.aspx

您必须实现的属性可能看起来令人望而生畏,但除非您需要特定功能(例如 ResetPassword),否则您可以简单地抛出 NotImplementedException。仅对您将使用的内容进行编码。

【讨论】:

  • 感谢您的详细解释。有什么方法可以挽救我所拥有的东西或过渡到更好的解决方案而不会废弃所有东西?我希望身份验证信息在我的所有母版页、内页、类等中都可用,就像我使用会员资格一样。
【解决方案3】:

为什么不按照微软推荐的方式去做呢?

http://msdn.microsoft.com/en-us/library/9wff0kyh.aspx

我已经通过这种方式完成了自定义身份验证,并且效果很好。


这是另一个有用的链接:

Link

【讨论】:

  • 该站点当前是经典 ASP,我正在尝试将其逐节转换为 .NET,因此我需要能够完全控制该解决方案。我曾考虑过自定义会员提供程序,但这超出了我的需要,我仍然需要为 ASP 端提供一种集成方式。
  • 不是一个真正的选择.. 有数百个 asp 包含、一个购物车和一堆其他遗留的东西,别无选择,只能在 .net 中做我能做的,所以我不必保留更新遗留代码。如果必须,我将在每个页面上嵌入对 auth 的调用,或者为我的所有页面设置基类以继承。
  • 听上去像是一种皇家的痛苦。我已经使用上述技术绑定到外部 SSO 系统,并且非常轻松......所以如果你可以让它工作,我推荐它。
【解决方案4】:

您对 IHttpModule 所做的似乎是解决此类问题的好方法。微软所说的 http 模块的目的之一是启用任何类型的特殊身份验证。当 http 模块初始化时,它对新请求使用相同的实例。由于您没有任何全局变量,我不太确定如何解决您的线程安全问题。看来你只是在读一些数据,所以请详细说明!

【讨论】:

  • 感谢您的评论。 CurrentUser 应该保存当前用户的详细信息。它实际上在测试中效果很好......不幸的是,它有一些设计缺陷。
猜你喜欢
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 2012-03-02
相关资源
最近更新 更多