2013-02-12 6 views
1

Je me sers d'une classe OAuthBase trouvé HERE dans mon SSIS 2008 C# Script Components (.NET 3.5). Cela fonctionne correctement, mais j'ai récemment rencontré le problème suivant: si j'exécute plusieurs composants de script dans la même tâche de flux de données, en utilisant la méthode GenerateNonce dans la classe OAuthBase ci-dessus, je me retrouve avec le même nonce (nombre aléatoire).fil générateur de nombres aléatoires sécurité/string pour un nonce OAuth en C#

Voici un extrait de la classe OAuthBase qui génère le nonce:

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

Dans chaque composant de script que je suis en utilisant ce code C# pour lancer la classe et générer un nonce:

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

A partir de mes recherches, je pense que cela est lié au fait que ce n'est pas thread safe? Je ne suis pas totalement sûr.

Je ne suis en mesure d'exécuter .NET 3.5 dans SSIS 2008, donc je sais certains des nouveaux trucs introduites dans .NET 4.0, je ne peux pas utiliser.

Toutes les idées sur la façon dont je peux soit modifier la classe OAuthBase et/ou mon code C# composant script?

+0

Ce nonce a très peu de valeurs possibles. Même le bug de threading de côté n'est pas unique par tous les moyens. – usr

+0

@usr - merci. Je me demandais à ce sujet. Peut-être que je fais juste quelque chose comme 'return Guid.NewGuid.ToString();'? Je ne suis pas tout à fait sûr combien de temps mon nonce peut être (frappant Magento REST API). – jared

Répondre

5

Si vous créez plusieurs instances de OAuthBase en même temps, il est tout à fait possible que l'instance individuelle ait une instance Random avec le même germe, qui par défaut est le nombre de ticks actuel. Cela signifie donc que les instances individuelles de Random ont peut-être été créées avec la même graine. Essayez de rendre l'instance Random statique. Mais depuis Random is not thread safe. Vous devez protéger l'accès à celui-ci.

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

Mais comme d'autres l'ont suggéré, puisque vous ne disposez pas d'une source de hasard, vous voudrez peut-être cryptographiquement forte à examiner d'autres façons de générer votre valeur.

// 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); 
} 
+0

combiner avec le remplacement aléatoire avec [RNGCryptoServiceProvider] (http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx) comme [usr ladite] (http://stackoverflow.com/a/14843988/80274) et vous aurez la réponse parfaite. –

+0

@ScottChamberlain mis à jour pour inclure un exemple en utilisant RNGCryptoServiceProvider –

+2

Juste un FYI à tout le monde au cas où ils ne savaient pas, [RNGCryptoServiceProvider est thread-safe uniquement pour les versions 3.5 et plus récente de .NET] (http://msdn.microsoft.com/ en-us/library/system.security.cryptography.rngcryptoserviceprovider% 28v = vs.85% 29.aspx # threadSafetyToggle), donc si vous ciblez 3.0 ou plus, vous devez toujours utiliser un verrou. –

Questions connexes