web-dev-qa-db-ja.com

ASP.NET MVC 5の基本認証

ASP.NET MVC 5で基本認証を実装するには、どの手順を実行する必要がありますか?

OWINはCookieなしの認証をサポートしていないので、基本認証は一般的に可能ですか?

ここにカスタム属性が必要ですか?これらの属性がどのように機能するかはわかりません。

39
Sonic

カスタムのActionFilter属性を使用して、このシンプルで効果的なメカニズムを使用できます。

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    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 override void OnActionExecuting(ActionExecutingContext 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;
        }
        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
        /// thanks to eismanpat for this line: http://www.ryadel.com/en/http-basic-authentication-asp-net-mvc-using-custom-actionfilter/#comment-2507605761
        filterContext.Result = new HttpUnauthorizedResult();
    }
}

これを使用して、基本認証の下にコントローラー全体を配置できます。

[BasicAuthenticationAttribute("your-username", "your-password", 
    BasicRealm = "your-realm")]
public class HomeController : BaseController
{
   ...
}

または特定のActionResult:

public class HomeController : BaseController
{
    [BasicAuthenticationAttribute("your-username", "your-password", 
        BasicRealm = "your-realm")]
    public ActionResult Index() 
    {
        ...
    }
}

追加情報が必要な場合は、このトピックで書いた このブログ投稿 をご覧ください。

73
Darkseal

これを行うには、カスタム属性を使用します。オープンソースプロジェクトのベース認証 SimpleSecurity をサポートするカスタム属性の実装があります。これは こちらからダウンロード です。使用方法を示すリファレンスアプリケーションがあります。もともとはMVC 4のSimpleMembershipで動作するように開発されたもので、最近 MVC 5でASP.NET Identityを使用するように移植されました です。

13
Kevin Junghans

そのコードには重大なセキュリティ上の欠陥があるため、Darksealが共有する回答を修正したかったのです。書かれているように、そのアクションフィルターはres.End()が呼び出されたときに実際にリクエストを終了しません。ユーザーは資格情報の入力を求められ、資格情報が一致しない場合は401応答が返されますが、コントローラーアクションはサーバー側で実行されます。要求が適切に終了し、アクションメソッドに進まないようにするには、filterContext.Resultプロパティを何かに設定する必要があります。

サードパーティからデータフィードを受信するWebサービスエンドポイントを保護しようとしていたので、これは私の状況にとって特に悪いことでした。書かれているように、このアクションフィルターは何も保護しませんでした。データがまだアクションメソッドを介してプッシュされているからです。

私の「クイックフィックス」は以下のとおりです。

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    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 override void OnActionExecuting(ActionExecutingContext 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;
        res.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
        filterContext.Result = new HttpUnauthorizedResult();
    }
}
8
PatrickGaule

@Darksealからのすばらしい回答。 ASP.NET Web APIで使用するために再利用された同じコードを次に示します(MVCのいとこに近い)。同じ考え方で、名前空間とコンテキストクラスがわずかに異なります。まったく同じ方法でクラスとメソッドに追加します。

using System.Web.Http.Controllers;
using System.Web.Http.Filters;

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    public string BasicRealm { get; set; }
    protected string Username { get; set; }
    protected string Password { get; set; }

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

    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        var req = filterContext.Request;
        var auth = req.Headers.Authorization;
        if (auth?.Scheme == "Basic")
        {
            var cred = Encoding.ASCII.GetString(Convert.FromBase64String(auth.Parameter)).Split(':');
            var user = new { Name = cred[0], Pass = cred[1] };
            if (user.Name == Username && user.Pass == Password) return;
        }
        filterContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        filterContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", BasicRealm ?? "YourRealmName"));
    }
}
3
Neil Laslett

HTTP基本認証にはCookieは必要ありません。 HTTPリクエストのHEADERに基づいています。ヘッダーの名前はAuthorizationで、その値はユーザー名とパスワードを組み合わせて文字列「username:password」(すべてbase64エンコード)にする必要があります。

心からASP.NET MVCで基本認証を使用したことはありませんが、Web APIを使用してカスタム属性を作成しました(WebAPIの場合は here またはMVCの場合は here から開始できます)。

2
imperugo

このパッケージを Nuget (AuthPackage)で試すことができます。これにより、asp.net mvcに認証を簡単に追加できます。

  1. パッケージマネージャーコンソールを使用してパッケージをインストールします。

    インストールパッケージAuthPackage

  2. (appSettings)でWeb.configに接続文字列を追加します。

     <add key="connectionString" value="connectionStringHere" />
    
  3. ユーザーを登録、ログイン、ログアウトする準備ができました

例:

 public async Task<ActionResult> SignIn()
    {
        var context = System.Web.HttpContext.Current;
        AuthUser authUser = new AuthUser(context);
        await authUser.SignIn("[email protected]", "123456");
        return RedirectToAction("Index", "Home");
    }

ドキュメントを読むことができます こちら

1
Waleed Chayeb

私たちのアプリケーションは、Web.configの次のコードのために、「誤って」基本認証を使用しました。

<system.webServer>
    <modules>
        <remove name="FormsAuthentication" />
    </modules>
    ... other stuff
</system.webServer>

それ以外の場合、アプリケーションはフォーム認証を使用するように構成されます。そうでなければ、通常のフォーム認証が使用されていた場合は常に、ブラウザ認証ウィンドウがポップアップ表示されました。

0
Charles Burns