简体   繁体   English

在ASP.net中使用静态方法进行安全验证是不明智的吗?

[英]Is it unwise to have a static method be used for security validation in ASP.net?

I have a static method like this 我有一个像这样的静态方法

public static string DoSomethingToString(string UntrustedString)
{
//parse format and change string here.
return newString.
}

Since I know that multiple calls to: 因为我知道多次调用:

static int myInt=0;
public static int AddNumber()
{
lock(someObject)
{
myInt++;
return myInt;    
 }
}

will return an ever increasing number (that is shared among pages), I'm not sure how local the variables will be treated in DoSomethingToString(); 将返回一个不断增加的数字(在页面之间共享),我不确定在DoSomethingToString()中如何处理变量的局部性;

I'd like to learn the conditions in which a static method can safely/unsafely be used in ASP.net just to put my multi-threaded brain to rest on this topic. 我想学习静态方法在ASP.net中安全/不安全地使用的条件,只是为了让我的多线程大脑依赖于这个主题。

UPDATE: 更新:

Most of the discussion has been around value types. 大多数讨论都围绕着价值类型。 How do I know when it's safe to call methods (explicitly or implicitly) that change my reference types? 我怎么知道何时调用方法(显式或隐式)来改变我的引用类型是安全的? Is it enough to looking at MSDN documentation and only use methods where it says "threadSafe"? 是否足以查看MSDN文档并仅使用称为“threadSafe”的方法?

One example if what I call an implicit change is using String.Split() since it's part of the same class. 我称之为隐式更改的一个例子是使用String.Split(),因为它是同一个类的一部分。 I think there is a likelihood that some security characteristics are shared and there is less worry/diligence needed. 我认为有可能会分享一些安全特性,并且需要减少担心/勤勉。 (?) (?)

What I'm calling an explicit change (for lack of a better word right now) is calling another method to do work... which can be static or an instance class. 我所谓的显式更改(因为现在缺少更好的词)是调用另一种方法来做工作......可以是静态的或实例类。 I think that more background/research work needs to be done to ensure that each object and method is ThreadSafe. 我认为需要做更多的背景/研究工作来确保每个对象和方法都是ThreadSafe。

For the sake of discussion assume I have a method with this signature: 为了便于讨论,假设我有一个带有此签名的方法:

ValidateStringAndContext(string untrustedString, Object myCustomUserContext)

and it has a static method that references the following object 它有一个引用以下对象的静态方法

public SecurityChecker
{
public static object CheckSecurityStatic(string DirtyData)
{
//do string.split
//maybe call a database, see if it's a token replay 
//

//OR  - alternate implementation
SecurityChecker sc = new SecurityChecker();
 if (sc.CheckSecurity(DirtyData))
  {
  myCustomUserContext.Property1 = new GUID()
  }
return myCustomUserContext;
}


public class bool CheckSecurity(string DirtyData)
{
//do string.split
//maybe call a database, see if it's a token replay 
// return true if OK return false if not
}
}

Revised Question 修订问题

Would I run into concurrency issues (variables overwriting each other) if the static "utilities" class I create were to create an instance of another object and then call the method --versus-- simply calling a static method directly? 如果我创建的静态“实用程序”类是创建另一个对象的实例然后调用方法--versus--直接调用静态方法,我会遇到并发问题(变量覆盖彼此)吗?

Each thread calling your static method has its own call stack. 调用静态方法的每个线程都有自己的调用堆栈。 Every call to DoSomethingToString() has its own copy of the method's variables, completely independant of any other call to that method on another thread (unless you declare a variable as static, thats what you may be getting confused with - a static variable has only one instance that is accessible to multiple threads in your program). 每次对DoSomethingToString()的调用都有自己的方法变量副本,完全独立于另一个线程上对该方法的任何其他调用(除非你将变量声明为静态,这就是你可能会混淆的东西 - 静态变量只有一个可供程序中多个线程访问的实例)。

As always, you need to consider concurrency when multiple threads are accessing a shared resource. 与往常一样,当多个线程访问共享资源时,您需要考虑并发性。 When a resource only exists within the context of a method call, concurrency is a non-issue. 当资源仅存在于方法调用的上下文中时,并发性不是问题。

See also: https://stackoverflow.com/questions/511378/net-static-methods-and-its-effects-on-concurrencyt 另见: https//stackoverflow.com/questions/511378/net-static-methods-and-its-effects-on-concurrencyt

There are some very important points that have more to do with the code that is not visible than the code shown in the question... 有一些非常重要的要点与代码中没有可见的代码有关...

The DoSomeThingToString method is static, and any variables declared within that method will be local to that thread's call stack. DoSomeThingToString方法是静态的,并且在该方法中声明的任何变量都将是该线程的调用堆栈的本地变量。 If the variables in use are defined outside the function, you will have race conditions on that memory. 如果使用的变量是在函数外部定义的,那么您将在该内存上具有竞争条件。 Be sure it looks like this, using only local variables: 确保它看起来像这样,只使用局部变量:

public static string DoSomethingToString(string UntrustedString)
{
    var newString = UntrustedString;
    // operations on newString...
    return newString;
}

The AddNumber method could be subject to other problems that might not be obvious. AddNumber方法可能会受到其他可能不明显的问题的影响。 If this is really what you are trying to do, to add a number, do it like this: 如果这是你想要做的,添加一个数字,就这样做:

System.Threading.Interlocked.Increment(ref myInt);

The Interlocked.Increment method guarantees that the operation will be completed in one clock cycle. Interlocked.Increment方法保证操作将在一个时钟周期内完成。

Otherwise, the use of the lock keyword can be tricky in some rare situations. 否则,在某些罕见的情况下使用lock关键字会很棘手。 Here are some rules of thumb. 这是一些经验法则。 Always lock on an object that you both create and hold the reference to, and even better, that you can never change. 始终锁定您创建并保持对其的引用的对象,甚至更好,您永远无法更改。 That means: readonly, and assigning the memory address upon creation of the class. 这意味着:readonly,并在创建类时分配内存地址。 That looks like this: 看起来像这样:

static int myInt=0;
static readonly object aGoodLock = new object();
public static int MoreComplexIntStuff()
{
    lock(aGoodLock)
    {
        // Do stuff with myInt...
    }
    return myInt;
}

Also, this isn't the whole story. 而且,这不是全部。 Another gotcha is that anytime the variable myInt is accessed, even if it's in another part of this class - or if it's public and used somewhere else, you need to wrap it with a lock. 另一个问题是,无论何时访问变量myInt,即使它在该类的另一部分中 - 或者如果它是公共的并在其他地方使用,您需要用锁来包装它。 And not just any lock, but the same one that you're using, aGoodLock. 而且不仅仅是锁定,而是你正在使用的锁定,aGoodLock。

The best way to help your fellow developers (and perhaps your own long-term memory) with this is to make the variable and the lock that wraps it private , and to expose myInt using a Property where you would be careful to use the lock in the get and set. 用这个来帮助你的开发人员(也许你自己的长期记忆)的最好方法是使变量和将它包装成private的锁,并使用一个你要小心使用锁的属性来暴露myInt。得到和设定。

I get the feeling that you are thinking that variables can be only instance or static, and forgetting that local variables are different to either. 我觉得你认为变量只是实例或静态,而忘记了局部变量也不同。 Consider: 考虑:

public class MyClass
{
    public int InstanceInt;
    public static int StaticInt;
    public int InstanceMethod()
    {
        int i = new Random().Next(1, 50);
        return i;
    }
    public static int StaticMethod()
    {
        int j = new Random().Next(1, 50);
        return j;
    }
}

Here InstanceInt is an instance variable, and StaticInt a static variable. 这里InstanceInt是一个实例变量,而StaticInt是一个静态变量。 Both of these require locking if they are going to be accessed by different threads, however, InstanceInt is only going to be accessed by different threads if an instance of MyClass is accessed by different threads. 如果它们将被不同的线程访问,则这两者都需要锁定,但是,如果不同的线程访问MyClass的实例,则InstanceInt将仅由不同的线程访问。 This could happen with static MyClass AllThreadsSeeMe = new MyClass() , storage in a static collection, explicitly passing it to another thread, or so on, but otherwise will not. 这可能发生在static MyClass AllThreadsSeeMe = new MyClass() ,静态集合中的存储,显式传递给另一个线程,等等,否则就不会发生。 StaticInt meanwhile is inherently accessible to all threads running in the application, even if you take care to make sure that no instance of MyClass is shared between threads. StaticInt同时对应用程序中运行的所有线程都是固有可访问的,即使您注意确保线程之间没有共享MyClass实例。

Meanwhile, i and j are both local to their functions. 同时, ij都是其功能的本地。 Each thread calling the function will be given their own copy of i or j , irregardless to how many threads could call them. 调用该函数的每个线程都将获得自己的ij副本,而不管有多少线程可以调用它们。 Hence they are inherently thread-safe. 因此,它们本质上是线程安全的。 It is only if either of these methods alter a static or instance variable, or read a mutable static or instance variable that could be altered by a different method, that they are not thread-safe (immutable - readonly - variables are also threadsafe because there's no way another thread can change their value, given that no thread at all can change it). 只有当这些方法中的任何一个改变静态或实例变量,或者读取可以通过不同方法改变的可变静态或实例变量时,它们才是线程安全的(不可变 - readonly - 变量也是线程安全的,因为它是没有其他线程可以改变它们的值,因为根本没有线程可以改变它)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM