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

C# C中OAuth nonce的线程安全随机数/字符串生成器#,c#,.net-3.5,ssis,script-component,C#,.net 3.5,Ssis,Script Component,我一直在使用SSIS 2008 C#脚本组件(.NET 3.5)中的OAuthBase类 它一直工作得很好,但最近我遇到了一个问题,如果我在同一个数据流任务中执行多个脚本组件,使用上述OAuthBase类中的GenerateNonce方法,我最终会得到相同的nonce(随机数) 下面是生成nonce的OAuthBase类的摘录: using System; using System.Security.Cryptography; using System.Collections.Generic;

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

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

下面是生成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();
    }
  }
}
在每个脚本组件中,我使用以下C#代码初始化类并生成nonce:

        OAuthBase oAuth = new OAuthBase();
        string nonce = oAuth.GenerateNonce();
从我周围的搜索中,我认为这与线程不安全有关?我不完全确定

我只能在SSIS 2008中运行.NET 3.5,因此我知道在.NET 4.0中引入的一些新东西我无法使用


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

目前,这个值可能很少。即使撇开线程错误不谈,它也不是唯一的。使用一个加密的强随机性源(),输出16个字节并将其base64。这就解决了所有这些问题。

如果同时创建多个
OAuthBase
实例,则完全可能单个实例将有一个具有相同种子的
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);
}

此nonce的可能值非常少。即使撇开线程错误不谈,它也不是唯一的。@usr-谢谢。我想知道。也许我只是做了一些类似于返回Guid.NewGuid.ToString()的事情?我不完全确定我的nonce可以持续多长时间(点击Magento REST API)。结合使用like替换Random,您将得到完美的答案。@ScottChamberlain更新为包含一个使用RNGCryptoServiceProvider的示例仅供其他人参考,以防他们不知道,因此,如果您的目标是3.0或更高版本,您仍然需要使用锁。请注意Base64的工作原理,从上一个方法生成的字符串长度将是传入的字节数组长度的4/3(
length
)(剩余部分将向上取整,并在末尾填充
=
),感谢您的帮助和解释。一个小问题是
随机。GetNonZeroByte
应该是
随机的。GetNonZeroBytes
(我试图编辑答案,但它不允许我在每个方法中添加2个)。