私のWebアプリケーションには、AJAXの呼び出しを介して認証資格情報を送信するログインページがあります。ユーザーが正しいユーザー名とパスワードを入力した場合、すべて正常に動作します。
これは、ステップ3までは問題ありません。ダイアログをポップアップ表示したくないので、AJAXコールバック関数で401応答を処理したいです(たとえば、ログインページにエラーメッセージが表示されます。)もちろん、ユーザーにユーザー名とパスワードを再入力してもらいたいのですが、ブラウザの見苦しいデフォルトの認証ダイアログではなく、フレンドリーで安心できるログインフォームを表示してほしいです。
ちなみに、サーバーを制御することはできないため、カスタムステータスコード(つまり、401以外のもの)を返すようにすることはオプションではありません。
認証ダイアログを抑制する方法はありますか?特に、Firefox 2以降で[認証が必要]ダイアログを非表示にできますか? IE 6以降)で[ホスト]ダイアログに接続を抑制する方法はありますか?
編集
著者からの追加情報(9月18日):
ブラウザの認証ダイアログのポップアップに関する実際の問題は、ユーザーに十分な情報を提供しないということです。
ユーザーは、ログインページのフォームを介してユーザー名とパスワードを入力したばかりで、両方を正しく入力したと考えており、送信ボタンをクリックするか、Enterキーを押しました。彼の期待は、彼が次のページに連れて行かれるか、おそらく自分の情報を間違って入力したので、もう一度やり直すべきだと言われることです。ただし、代わりに、予期しないダイアログボックスが表示されます。
ダイアログは、ユーザーがユーザー名とパスワードを入力しただけdidの事実を認めません。問題があったことと、彼が再試行する必要があることを明確に述べていません。代わりに、ダイアログボックスは「サイトは言う: '[realm]'」のような不可解な情報をユーザーに提示します。ここで、[realm]は、プログラマーだけが愛せる短いレルム名です。
Webブラウザの設計者は注意します。ダイアログ自体がより使いやすい場合、認証ダイアログを非表示にする方法を尋ねる人はいません。ログインフォームを使用しているentire理由は、製品管理チームがブラウザーの認証ダイアログをひどいものと考えているためです。
私はこれが可能であるとは思わない-あなたがブラウザのHTTPクライアント実装を使用する場合、それは常にそのダイアログをポップアップします。 2つのハックが思い浮かびます:
たぶん、Flashはこれを別の方法で処理します(まだ試していません)。
独自のサーバーでアクセスしているサービスに「プロキシ」を設定し、ブラウザがそれらを認識しないように認証ヘッダーを少し変更することができます。
私はここで同じ問題に遭遇し、私の会社のバックエンドエンジニアは良いプラクティスと思われる動作を実装しました:URLへの呼び出しが401を返すとき、クライアントがヘッダーX-Requested-With: XMLHttpRequest
を設定している場合、サーバーはwww-authenticate
ヘッダーをドロップしますその応答で。
副作用は、デフォルトの認証ポップアップが表示されないことです。
API呼び出しのX-Requested-With
ヘッダーがXMLHttpRequest
に設定されていることを確認してください。もしそうなら、この良い慣行に従ってサーバーの動作を変更する以外に何もすることはありません...
次の両方の条件が満たされると、ブラウザーはログインプロンプトをポップアップします。
WWW-Authenticate
ヘッダーが応答に存在しますHTTP応答を制御できる場合、応答からWWW-Authenticate
ヘッダーを削除できます。ブラウザーはログインダイアログをポップアップ表示しません。
応答を制御できない場合は、応答からWWW-Authenticate
ヘッダーを除外するプロキシを設定できます。
私の知る限り(間違っている場合はお気軽に修正してください)、ブラウザがWWW-Authenticate
ヘッダーを受信すると、ログインプロンプトを防ぐ方法はありません。
この質問とその答えは非常に古いことを理解しています。しかし、私はここで終わった。他の人もそうでしょう。
401を返すWebサービスのコードにアクセスできる場合。401の代わりにこの状況で403(禁止)を返すようにサービスを変更するだけです。ブラウザは、403に応答して資格情報を要求しません。特定のリソースに対して許可されていない認証済みユーザーの正しいコード。これはOPの状況のようです。
403のIETFドキュメントから:
アクセスを取得するのに十分ではない有効な資格情報を受信するサーバーは、403(禁止)ステータスコードで応答する必要があります
Mozillaでは、XMLHttpRequestオブジェクトを作成するときに次のスクリプトでそれを実現できます。
xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);
2行目では、ダイアログボックスが表示されません。
jan.vdberghには真実があります。サーバー側の401を別のステータスコードに変更できる場合、ブラウザはポップアップをキャッチしてペイントしません。別の解決策は、別のカスタムヘッダーのWWW-Authenticateヘッダーを変更することです。別のブラウザでサポートできない理由は信じられません。Firefoxのいくつかのバージョンでは、mozBackgroundRequestでxhrリクエストを実行できますが、他のブラウザでは?ここでは、Chromiumのこの問題に関して興味深い link があります。
Mozillaランドでは、XMLHttpRequestのmozBackgroundRequestパラメーター( docs )をtrueに設定すると、これらのダイアログが抑制され、リクエストが単に失敗します。ただし、クロスブラウザのサポートがどれほど優れているかはわかりません(失敗したリクエストのエラー情報の品質がブラウザ間で非常に優れているかどうかも含めて)。
どのサーバー技術を使用していますか?認証に使用する特定の製品はありますか?
ブラウザはその役割を果たしているだけなので、401ステータスコードを返さないようにサーバー側で変更する必要があると思います。これは、認証が失敗したときに再びフォームを返すカスタム認証フォームを使用して実行できます。
MVC 5とVPNでも同じ問題があり、VPNを使用してDMZの外にいるときはいつでも、このブラウザーメッセージに応答する必要があります。netを使用して、使用エラー
<customErrors defaultRedirect="~/Error" >
<error statusCode="401" redirect="~/Index"/>
</customErrors>
これまでのところ、ホームコントローラーの下のインデックスアクションがユーザーを検証するため、機能しています。ログオンに失敗した場合、このアクションのビューには、ディレクトリサービスに渡されたLDAPクエリを使用してユーザーをログインさせるために使用するログインコントロールがあります。
DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
DirectorySearcher Dsearch = new DirectorySearcher(entry);
Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
Dsearch.PropertiesToLoad.Add("cn");
これはこれまではうまく機能していましたが、私はまだテスト中であり、上記のコードは実行する理由がなかったため、削除される可能性があることをお知らせする必要があります...テストには現在、2番目のセットのケースを発見しようとする試みが含まれていますコードのそれ以上の使用です。繰り返しになりますが、これは進行中の作業ですが、何らかの助けになるか、いくつかのアイデアを求めて脳を動かす可能性があるため、今すぐ追加することにしました...すべてのテストが完了したら、最終結果で更新します。
Node、Express、Passportを使用していますが、同じ問題に苦労していました。 www-authenticate
ヘッダーを空の文字列に明示的に設定することで機能するようになりました。私の場合、次のようになりました。
(err, req, res, next) => {
if (err) {
res._headers['www-authenticate'] = ''
return res.json(err)
}
}
私はそれが誰かを助けることを願っています!
これらのunsing C#の場合は、400
ではなく401
を返すActionAttribute
と、基本認証ダイアログを「飲み込む」ものがあります。
public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
filterContext.Result = new HttpStatusCodeResult(400);
}
}
次のように使用します:
[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
// your code goes here
}
これで時間を節約できることを願っています。