2009-07-03 23 views
4

Webアプリケーションのセキュリティでは、非永続的なCookieを持つFormsAuthentication/MembershipProviderを使用しています。フォーム認証のCookieにパスワードを保存する - ASP.NETとWCFの呼び出し

私のアプリケーションは、いくつかのWebサービスとやりとりします。これらは、メンバーシッププロバイダも使用します。

ユーザーパスワードはデータベースにハッシュされます。

問題は、Webサービスが、ページがロードされるたびにユーザー名とパスワードを使用してWebサービスで認証する必要があるアプリケーションにログインする人です。しかし、一度ユーザーがパスワードを入力すると、ハッシュされているため、パスワードは取り戻せなくなります。

ユーザーがWebサービスで認証できるように、パスワードを認証Cookieに保存できるかどうかは疑問でした。

またはもっと良いアイデア!

EDIT 私はDOWNそのルートを行く前に解決するにはWANT力学に4件のコメントを... BELOW JOHNSのアイデアを似ていますが、HAVE

答えて

9

@awayのトークンを使用すると、資格情報を保存するよりも優れています。

トークンについては、いくつかのランダムなGUIDを生成してデータベースに格納することができます。

ASP.NETアプリケーションとWCFサービスとの間の調整を必要としない別の方法として、署名されたドキュメントをトークンとして送信することができます。

  1. 署名時刻、ユーザー名、署名者名(ASP.NETアプリケーション)を使用してXMLまたはJSONドキュメントを作成します。
  2. 上記のドキュメントのハッシュを生成します。
  3. 非対称暗号化(秘密鍵を使用)を使用してハッシュに署名します。

すべてのWCFは、ハッシュと署名を検証する必要があります。したがって、これは同じデータベースに当たることを伴わない。署名された時刻を使用すると、一定の時間内にトークンを期限切れにすることができます。

編集:このアイデアは、public-key cryptography(非対称キーアルゴリズム、公開/秘密キーとも呼ばれます)に基づいています。秘密鍵で何かを暗号化すれば、対応する公開鍵を使ってのみ復号化することができます。公開鍵で何かを暗号化すれば、それに対応する秘密鍵だけを使って解読することができます。コードがC#のように見える方法については、Implementing RSA in C#を参照してください。なぜこれは役に立ちますか?デジタル署名を実装するためにこれを使用できるからです。デジタル署名は、私だけが何かを書いたことを証明する方法であり、誰も誰も書いていません。

上記の手順を実行すると、署名が生成されます。最初に、 "この男を人にしてください"という規範的な形式を定義する必要があります。通常、非対称キーアルゴリズムは大きすぎる入力を処理できないため、ハッシュを生成し、ASP.NETアプリケーションの秘密キーを使用してハッシュを暗号化します。結果の署名は、アプリケーションの公開鍵を使用してのみ解読することができます。最後に、3つのコンポーネント(元のドキュメント、ハッシュ、および署名)をXMLやJSONなどの形式にパッケージ化し、トークンとして送信できます。

たとえば、JSON形式をすべて使用するとします。

{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1"} 

次に、あなたがbyte[]で上記の文字列のSHA-1ハッシュを生成し、次のようになりますされ、modified Base64 encodingか何かでそれをエンコード:まず、元は「文書中のこの男は聞かせて」:

b2YgYW55IGNhcm5hbCBwbGVhc3VyZS4 

上記は偽の文字列ですが、実際のものは長く見える場合があります。その後、ハッシュbyte[]を取るので、修正をBase64にすぎということを符号化する別のbyte[]を生成RSAを使用して、それを暗号化:

mxlIGdlbmVyYXRpb24gb2Yga25vd2xfo34 

最後に、あなたが上記のすべて格納するための別のJSONドキュメントを作ります。

{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1","Hash":"b2YgYW55IGNhcm5hbCBwbGVhc3VyZS4","Signature":"mxlIGdlbmVyYXRpb24gb2Yga25vd2xfo34"} 

最終的なJSONドキュメントは、パスワードなしのトークンになります。それをWCFサービスに渡します。 WCFサービスは、ハッシュと署名を削除することで、元の文書を作成、トークンを取ります

{"UserName":"Foo","SignedTime":"2009-07-09T00:00:00","Signer":"ASP.NET APP1"} 

はハッシュを生成し、それは同じだ確認するために、同じアルゴリズムに従ってください。 ASP.NETアプリケーションの公開鍵を使用して署名を復号化し、それがハッシュになるかどうかを確認します。この時点で、文書は署名者によって署名されていることが確認されます。現在の時刻と署名時刻を確認し、トークンが有効かどうかを確認します。必要なのは、XMLからロードできる2つのコードベースの間に公開鍵を配布する方法だけです。

7

のベストプラクティスは、自分のユーザー名で認証を行うユーザーを必要としないことであろうすべての要求に対してパスワードを入力します。

代わりに、最初の認証では、Webサービスは何らかの種類の認証トークンを返す必要があります。これはどこかに保存する必要があります。フォーム認証チケットではなく、セッション状態で保存することをお勧めします。

Webサービスからのチケットが期限切れになると、フォーム認証チケットも期限切れになることが考えられます。これにより、ユーザーはサイトに再度ログインし、ユーザー名とパスワードを提供する必要があります。 Webサービスからのチケットの再格納、Webサービスからのチケットの保存などに使用します。

+1

ダウンボートの理由を明記してください。誰もが間違いを言っていないなら、間違いから学ぶことはできません。 –

+0

あなたの提案するアプローチは私の状況にとって理想的ですが、これを実装する方法の詳細は不明です:1)WCFサービスは明示的なログインメソッドを実装して、ユーザー名とパスワードを認証して認証トークンを返すべきですか? 2)クライアントの資格情報タイプはどのようにすべきですか? 3)認証トークンを後続のリクエストに渡すために推奨されるメカニズムは何ですか?各サービスメソッドへの明示的なパラメータとして、またはUserName認証を使用するときにはユーザー名とパスワードのような「背景」があります。 – AJM

+0

また、4)カスタムセキュリティトークン(http://msdn.microsoft.com/en-us/library/ms731872.aspx)を作成する必要がありますか? ありがとうございます。 – AJM

2

Webアプリケーションでは、LoginコントロールのAuthenticateイベントを設定して、新しいサービスプロキシをインスタンス化し、プロキシのClientCredentialsでユーザー名/パスワードを設定します。

プロキシ経由でサービスを呼び出すと、WCFはこれらの資格情報をセキュリティ保護されたチャネルを通じてサービスに渡し、認証に使用します。

これで、プロキシをセッションに格納して、チャネル状態と秘密鍵を持つため、サービスへのアクセスに使用するだけで済みます。

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e) 
{ 
    bool Authenticated = false; 
    try 
    { 
     MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint"); 
     proxy.ClientCredentials.UserName.UserName = LoginControl.UserName; 
     proxy.ClientCredentials.UserName.Password = LoginControl.Password; 

     //It doesn't really matter what is called or what it does because 
     //Membership Provider for the Service does the authentication. 
     string retval = proxy.login("Logging in"); 

     //Now that channel is established the proxy needs to be kept 
     //since it contains the channel state which includes a private key 
     Session["MyServiceProxy"] = proxy; 
     Authenticated = true; 
    } 
    catch (Exception ex) 
    { 
     //Login Error... 
    } 
    e.Authenticated = Authenticated; 
} 
+0

プロキシの資格情報を保存するのはOKですが、好奇心をそそるだけで、HTTPSを使用してWebサービスにアクセスする場合にのみ、次のことが当てはまります。 * WCFは、これらの資格情報を安全なチャネルで渡し、チャネル状態と秘密鍵を持つので、サービスへの今後のアクセスに使用します* – Arjan

+0

はい、Web層とサービスの間に安全なチャネルを設定する必要がありますそれはHTTPSである必要はありません。 WCFは、このチャネルをセキュリティで保護するための複数のメカニズムを提供します。これらのオプションについてここで議論するスレッドがあります:http://stackoverflow.com/questions/232500/how-to-configure-security-when-calling-wcf-service-from-net-2-0-client – RonnBlack

関連する問題