2009-03-14 10 views
13

Ho una semplice applicazione client-server basata su TcpClient/TcpListener e SslStream. I client possono autenticarsi sul server utilizzando un certificato X509 o inviando un nome utente e una password dopo che lo SslStream è stato stabilito.Come utilizzare System.IdentityModel nella propria applicazione client-server

WCF si avvale della System.IdentityModel spazio dei nomi per l'autenticazione, ma apparently che può essere utilizzato in applicazioni arbitrarie - che sembra interessante. Le informazioni su come farlo sono scarse (o il mio Google foo è debole oggi).

Quindi, la mia domanda è: Cosa devo fare per integrare System.IdentityModel con la mia applicazione? Non sono sicuro di aver bisogno di tutta quella roba ClaimSet, ma sarebbe bello se gli utenti potessero accedere utilizzando il proprio account Windows o qualsiasi altro meccanismo di autenticazione fornito. (Purtroppo non posso semplicemente passare a WCF ma devo usare il protocollo personalizzato, anche se posso apportare alcune modifiche ad esso, se necessario.)

risposta

17

Il mio Google foo era davvero debole. La risposta è proprio dietro il link nella mia domanda. Quindi ecco un paio di link a this blog nel caso qualcuno abbia la stessa domanda alla fine.

In primo luogo, si dovrebbe cercare di capire "che pretendono roba set":

Quindi, è necessario sapere dove insiemi di attestazioni provengono da:

Armati di questa conoscenza, in realtà diventa abbastanza semplice.

Se ho ben capito, il flusso di lavoro di base sarebbe qualcosa di simile:

  1. client crea una SecurityToken utilizzando un client SecurityTokenProvider
  2. serializza il SecurityToken utilizzando un server SecurityTokenSerializer
  3. deserializza il SecurityToken utilizzando a SecurityTokenSerializer
  4. Il server crea IAuthorizationPolicy s utilizzando un SecurityTokenAuthenticator
  5. Server crea AuthorizationContext da IAuthorizationPolicy s
  6. Fatto

Esempio:

// Create the SecurityTokenProvider 
var p = new UserNameSecurityTokenProvider("username", "password"); 

// Get the SecurityToken from the SecurityTokenProvider 
var t = p.GetToken(TimeSpan.FromSeconds(1.0)) as UserNameSecurityToken; 

// ... transmit SecurityToken to server ... 

// Create the SecurityTokenAuthenticator 
var a = new CustomUserNameSecurityTokenAuthenticator(
    UserNamePasswordValidator.None); 

// Create IAuthorizationPolicies from SecurityToken 
var i = a.ValidateToken(t); 

// Create AuthorizationContext from IAuthorizationPolicies 
var c = AuthorizationContext.CreateDefaultAuthorizationContext(i); 
ShowClaims(c.ClaimSets); 

Per X509SecurityToken s usano un X509SecurityTokenProvider/Authenticator. Per WindowsSecurityToken s c'è un WindowsSecurityTokenAuthenticator ma non un fornitore; invece, utilizzare il WindowsSecurityToken costruttore:

var t = new WindowsSecurityToken(WindowsIdentity.GetCurrent()); 

Questo funziona abbastanza bene. L'unica cosa che ho omesso finora è la serializzazione dei token. Esiste una classe SecurityTokenSerializer che ha un'implementazione nel framework .NET: la classe WSSecurityTokenSerializer fornita con WCF.

Serializzazione UserNameSecurityToken s e X509SecurityToken s funziona come un fascino (non hanno provato deserializzazione), ma WindowsSecurityToken s non sono apparentemente supportato dal serializzatore. Questo mi lascia con i due metodi di autenticazione che ho già (certificati e username/password) e, dato che non volevo che fosse lo AuthorizationContext, resterò con quello che ho :)

+1

Nel caso in cui qualcuno sia interessato, non sono sicuro che SecurityToken debba essere creato sul lato client e trasmesso a un server. Per la sicurezza X.509 ha molto più senso iniziare un SslStream con il server e creare X509SecurityToken dal certificato del server, per la sicurezza di Windows è possibile creare WindowsSecurityToken da negotiateStream.RemoteIdentity se si utilizza NegotiateStream. Per sicurezza nome utente/password, ovviamente, il nome utente e la password dovranno essere trasmessi. – dtb

7

Non ho la reputazione di pubblicare un commento sulla soluzione esistente, ma vorrei pubblicare i nuovi URL sui blog elencati nella soluzione, poiché quelli non funzionano più. Se qualcuno può cambiarlo in un commento, sarei molto grato.

+1

Ho modificato la risposta di @ dtb sopra per riflettere i collegamenti fissi.Dovrebbe comparire non appena revisionato. Grazie! –

+0

A partire da settembre 2016 alcuni collegamenti sono interrotti – JPK