C#中OAuth随机数的线程安全随机数/字符串生成器

jar*_*red 1 c# ssis script-component .net-3.5

我一直在使用中发现的OAuthBase类这里我SSIS 2008 C#脚本组件(.NET 3.5).

它一直运行良好,但最近我遇到了问题,如果我在同一个数据流任务中执行多个脚本组件,使用上面的OAuthBase类中的GenerateNonce方法,我最终得到相同的随机数(随机数).

以下是生成nonce的OAuthBase类的摘录:

using System;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace OAuth {
 public class OAuthBase {

    ....snip......

    protected Random random = new Random();

    public virtual string GenerateNonce() {
        // Just a simple implementation of a random number between 123400 and 9999999
        return random.Next(123400, 9999999).ToString();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在每个脚本组件中,我使用此C#代码来启动类并生成一个nonce:

        OAuthBase oAuth = new OAuthBase();
        string nonce = oAuth.GenerateNonce();
Run Code Online (Sandbox Code Playgroud)

从我的搜索周围,我认为这与它不是线程安全有关?我不完全确定.

我只能在SSIS 2008中运行.NET 3.5,所以我知道在.NET 4.0中引入的一些我不能使用的新东西.

关于如何修改OAuthBase类和/或我的C#脚本组件代码的任何想法?

JG *_* SD 5

如果同时创建多个实例OAuthBase,则单个实例完全可能具有Random具有相同种子的实例,默认情况下,种子是当前的滴答计数.所以这意味着Random可能已经使用相同的种子创建了各个实例.尝试将Random实例设为静态.但是因为Random不是线程安全的.您需要保护对它的访问.

private static readonly Random random = new Random();
private static readonly object randLock = new object();

public virtual string GenerateNonce()
{
    lock (randLock)
    {
        // Just a simple implementation of a random number between 123400 and 9999999
        return random.Next(123400, 9999999).ToString();
    }
}

// since you had protected access on random, I'm assuming sub classes want to use it
// so you'll need to provide them with access to it
protected int NextRandom(...)
{
    lock (randLock)
    {
         random.Next(...);
    }
}
Run Code Online (Sandbox Code Playgroud)

但正如其他人所建议的那样,因为你没有加密强大的随机性来源,你可能想看看其他方法来产生你的价值.

// RNGCryptoServiceProvider is thread safe in .NET 3.5 and above
// .NET 3.0 and below will need locking to protect access
private static readonly RNGCryptoServiceProvider random =
    new RNGCryptoServiceProvider();

public /*virtual*/ byte[] GenerateNonce(int length)
{
    // a default length could be specified instead of being parameterized
    var data = new byte[length];
    random.GetNonZeroBytes(data);
    return data;
}
// or
public /*virtual*/ string GenerateNonce(int length)
{
    var data = new byte[length];
    random.GetNonZeroBytes(data);        
    return Convert.ToBase64String(data);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果他们不知道的话,对其他人来说只是一个假设,[RNGCryptoServiceProvider只对3.5及更高版本的.NET提供线程安全](http://msdn.microsoft.com/en-us/library/system.security.cryptography .rngcryptoserviceprovider%28v = vs.85%29.aspx #threadSafetyToggle),因此如果你的目标是3.0或更早,你仍然需要使用锁. (2认同)