2

我一直在使用在我的 SSIS 2008 C# 脚本组件 (.NET 3.5) 中找到的OAuthBase类。

它一直工作正常,但最近我遇到了一个问题,如果我在同一个数据流任务中执行多个脚本组件,使用上述 OAuthBase 类中的 GenerateNonce 方法,我最终会得到相同的随机数(随机数)。

这是生成随机数的 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();
    }
  }
}

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

        OAuthBase oAuth = new OAuthBase();
        string nonce = oAuth.GenerateNonce();

根据我的搜索,我认为这与它不是线程安全的有关吗?我不完全确定。

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

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

4

2 回答 2

7

如果您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(...);
    }
}

但正如其他人所建议的那样,由于您没有强大的加密随机源,您可能希望寻找其他方法来产生您的价值。

// 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);
}
于 2013-02-12T23:49:54.207 回答
3

这个随机数的可能值非常少。即使是线程错误,它也不是唯一的。使用加密的强随机源 ( http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx ),输出 16 个字节和 base64 它们。这可以解决所有这些问题。

于 2013-02-12T23:45:00.480 回答