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#脚本组件代码的任何想法?
如果同时创建多个实例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)