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();

私の周りの検索から、これはスレッドセーフではないことに関連していると思いますか?よくわかりません。

.NET3.5はSSIS2008でしか実行できないため、.NET4.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 に答える