多くのブログ、MSDN ドキュメント、サンプル コード、およびその他のスタック オーバーフローに関する質問を読んで、しばらくの間これを理解しようとしてきましたが、まだこれを機能させていません。
これが私のシナリオです:
Windows Azure を使用して 2 つの Web ロールをホストしています。1 つは私の MVC4 Web API で、もう 1 つは Web API を使用する MVC4 Web アプリです。Web API にアクセスする .NET を使用する多数のクライアント アプリケーションもあります。
したがって、私の主なコンポーネントは次のとおりです。
- Web API
- ウェブアプリ
- .NET クライアント
Web アプリで「ホスト」されているフォーム認証を使用したいと考えています。組み込みの simplemembership 認証メカニズムを使用していますが、うまく機能します。Web アプリでアカウントを作成してログインできます。
ここで、これらの同じアカウントを使用して、Web アプリと任意の .NET クライアント アプリの両方から Web API を認証したいと考えています。
私はこれを行うための多くの方法を読みましたが、Web API で基本認証を使用するのが最も簡単なようです。現在、正確な問題を解決しているように見えるため、このコードを使用しています:フォーム認証、基本認証、およびSimpleMembershipの混合
私はこれを機能させることができません。Web アプリ (127.0.0.1:81) に正常にログインし、認証 (127.0.0.1:8081/api/values など) を必要とする Web API を呼び出そうとすると、401 (未承認)応答で呼び出しが失敗します。 . コードをステップ実行すると、WebSecurity.IsAuthenticated は false を返します。WebSecurity.Initialized は true を返します。
このコードを実装し、次のコードを使用して (ログイン後に) Web アプリから Web API を呼び出そうとしています。
using ( var handler = new HttpClientHandler() )
{
var cookie = FormsAuthentication.GetAuthCookie( User.Identity.Name, false );
handler.CookieContainer.Add( new Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain ) );
using ( var client = new HttpClient() )
{
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
// "Basic",
// Convert.ToBase64String( System.Text.ASCIIEncoding.ASCII.GetBytes(
// string.Format( "{0}:{1}", User.Identity.Name, "123456" ) ) ) );
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Cookie",
Convert.ToBase64String( System.Text.ASCIIEncoding.ASCII.GetBytes( User.Identity.Name ) ) );
string response = await client.GetStringAsync( "http://127.0.0.1:8080/api/values" );
ViewBag.Values = response;
}
}
ご覧のとおり、Cookie とユーザー名/パスワードの両方を使用してみました。明らかに私はクッキーを使いたいのですが、この時点で何かがうまくいくなら、それは良いステップです!
Web API の ValuesController は適切に装飾されています。
// GET api/values
[BasicAuthorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
Web API の Global.asax.cs で、SimpleMembership を初期化しています。
// initialize our SimpleMembership connection
try
{
WebSecurity.InitializeDatabaseConnection( "AzureConnection", "User", "Id", "Email", autoCreateTables: false );
}
catch ( Exception ex )
{
throw new InvalidOperationException( "The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex );
}
これは成功し、WebSecurity は後で初期化されたと言うので、この部分はすべて正常に動作していると思います。
私の構成ファイルには、 MSDNごとに必要な認証設定が一致しています。
API構成は次のとおりです。
<authentication mode="Forms">
<forms protection="All" path="/" domain="127.0.0.1" enableCrossAppRedirects="true" timeout="2880" />
</authentication>
<machineKey decryption="AES" decryptionKey="***" validation="SHA1" validationKey="***" />
Web アプリの構成は次のとおりです。
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" protection="All" path="/" domain="127.0.0.1" enableCrossAppRedirects="true" timeout="2880" />
</authentication>
<machineKey decryption="AES" decryptionKey="***" validation="SHA1" validationKey="***" />
これをローカルで試していることに注意してください (したがって 127.0.0.1 ドメイン) が、Azure でホストされているデータベースを参照しています。
Web ロール間で動作させることさえできないため、.NET クライアント アプリケーションからこれを試す必要はありません。クライアント アプリの場合、理想的には Web 呼び出しを行い、ユーザー名とパスワードを渡し、Cookie を取得し、さらに Web API 要求にその Cookie を使用します。
非常にシンプルに見え、私の要件を満たしているので、私が働いているものを手に入れたいと思います。
Thinktectureなどの他のソリューションは、必要以上に多くの機能があり、必要ではないように思われるため、まだ試していません。
私は何が欠けていますか?