11

フォーム認証が有効になっているASP.NET MVC5プロジェクトで作業しています。プロジェクトは現在テスト段階にあり、Azureでオンラインでホストされていますが、プロジェクトオーナーはサイトへのすべてのパブリックアクセスを無効にしたいと考えています(サイトの一部ではユーザーの認証が不要なため)。ASP.NET MVC5基本的なHTTP認証とAntiForgeryToken例外

このテストフェーズでは、linkから基本HTTP認証を実装することにしました。私はそうより良いスーツ、私のニーズにコードを変更しました:

public class BasicAuthenticationAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    public string BasicRealm { get; set; } 

    protected string Username { get; set; } 
    protected string Password { get; set; } 

    public BasicAuthenticationAttribute(string username, string password) 
    { 
     this.Username = username; 
     this.Password = password; 
    } 

    public void OnAuthorization (AuthorizationContext filterContext) 
    { 
     var req = filterContext.HttpContext.Request; 
     var auth = req.Headers["Authorization"]; 
     if (!String.IsNullOrEmpty(auth)) 
     { 
      var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':'); 
      var user = new { Name = cred[0], Pass = cred[1] }; 

      if (user.Name == Username && user.Pass == Password) 
       return; 
     } 

     var res = filterContext.HttpContext.Response; 
     var alreadySent = HttpContext.Current.Items.Contains("headers-sent"); 

     if (!alreadySent) 
     { 
      res = filterContext.HttpContext.Response; 
      res.StatusCode = 401; 
      res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 

     } 
    } 
} 

私もグローバルフィルタとして登録されました:私は、プロジェクトを実行したときただし、いくつかの問題がある

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorExtendedAttribute()); 
     filters.Add(new BasicAuthenticationAttribute(AppConfig.BasicUsername, AppConfig.BasicPassword)); 
    } 
} 

。このバージョンのコードを使用すると、正常にログインした後、常にフォームのログインページにリダイレクトされます。

 if (!alreadySent) 
     { 
      res = filterContext.HttpContext.Response; 
      res.StatusCode = 401; 
      res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 
     } 

私はCSHTMLファイルに

res.AppendHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Test")); 

Antiforgerytoken後

res.End(); 

を追加する場合は、HTTPヘッダーがされた後System.Web.HttpException

Serverは、ヘッダーを追加することはできませんスロー送信されます。

しかし、この場合、最終的に正常に認証されます。

フォーム認証を無効にすることはオプションではないため、この問題を解決する方法がわかりません。すべてのAntiForgeryTokensとその検証を削除することはできません。

+2

なぜあなたはこの方法を選んだのですか?独自の '認証フィルタ'を構築したい場合は、 'AuthorizeAttribute'から継承し、' IsAuthorized'関数をオーバーライドし、不正なリクエストに対して 'false'を返し、' HandleUnauthorizedRequest'関数でそれらを処理する必要があります。 – AnhTriet

+0

res.AppendHeader行でres.StatusCode行を反転するとどうなりますか? StatusCodeの値は "Body"の一部としてカウントされるので、ヘッダーがもう書き込まれなくなりますか?また、Andrewの回答を以下で検討してください。 –

+0

plzは基本認証を使用しません。あなたが参照する他の質問は6歳のようなものであり、さらに良い選択肢があったことに注意してください。参照:http://adrianotto.com/2013/02/why-http-basic-auth-is-bad/ – nothingisnecessary

答えて

1

res.AppendHeader(..)の前にこの行を試しましたか?

Response.ClearHeaders(); 
3

、それが以前のメンバーであったようにあなたは、単に多くのコードを記述することなく、ユーザーを認証することができ、これを使用してMVC 5に含まれているので、私は、ASP.NETのアイデンティティのメンバシッププロバイダを使用するためにあなたをお勧めします。 FormsAuthenticationメソッドを使用している場合と同様に、内部クッキーで外部ログインを使用することもできます。必要なのは、コードで簡単な設定を行うだけで、カスタムフィルタを作成する必要はありません。

1

req.End()でリクエストを終了する代わりに、filterContext.Resultを次のように設定したいと思います。 Resultをnull以外の値に設定すると、残りのMVCパイプラインの処理が中断され、ブラウザに応答が送信されますが、End()のようにレスポンスを閉じてはいけません。すでに送信されているヘッダーについて

これを試してみてください:

filterContext.Result = new HttpUnauthorizedResult();