27

ビューをレンダリングする前に、アプリケーションにユーザー名とパスワードを要求させることはできますか? Twitter API と同じように、アカウントに関する情報を取得します。

http://twitter.com/account/verify_credentials.xml

したがって、ビューをレンダリングする前に || ファイルにユーザー名とパスワードを挿入するように求めます。curl リクエストはユーザー名:パスワードに基づいているため、これはサーバー上で直接行われると思います。

curl -u user:password http://twitter.com/account/verify_credentials.xml

同じ構造に従って API を構築しようとしているので、ASP.NET MVC C# でこれを行う方法を知りたいです。私はすでにこれをルビーレールで使用しており、非常に単純です:

before_filter :authenticate

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
    username == "foo" && password == "bar"
end

[Authorize] フィルターは同じではないと思います。これは単なるリダイレクトであり、アカウント データベースに基づく Accounts Internal Controller にリダイレクトされます。この場合、別のデータベースを使用します。 webservice を使用して、情報が送信された後に検証を行います。しかし、ユーザーを要求し、その要求で資格情報を渡すアクションが必要です。

前もって感謝します


アップデート:

実際にこの認証を必要とするページ (つまり Twitter) をリクエストするには、そのリクエストでこれを宣言する必要があります。

request.Credentials = new NetworkCredential("username", "password");

そして、これはプロンプトされたユーザー名とパスワードを反映します。

したがって、まったく同じことですが、反対側から見ると、リクエストに応じて認証プロンプトに情報を提供できる場合、代わりにリクエストでこの認証を要求するにはどうすればよいでしょうか?

したがって、誰かが私のアプリケーションにリクエストを送信しようとするたびに、次のようになります。

http://myapplication/clients/verify_credentials

そのサーバープロンプトでユーザー名とパスワードを要求する必要があるため、たとえばcurlに関する情報を取得するには、次のようになります

curl -u user:password http://myapplication/clients/verify_credentials
4

4 に答える 4

48

基本認証を要求するには、401ステータスコードを返す必要があります。ただし、これを行うと、現在の認証モジュールがデフォルトの無許可ハンドラーを実行します(フォーム認証の場合、これはログインページにリダイレクトすることを意味します)。

ActionFilterAttribte認証モジュールがインストールされていないときに、希望する動作が得られるかどうかを確認するためにを作成しましたweb.config

public class RequireBasicAuthentication : ActionFilterAttribute {
   public override void OnActionExecuting(ActionExecutingContext filterContext) {
       var req = filterContext.HttpContext.Request;
       if (String.IsNullOrEmpty(req.Headers["Authorization"])) {
           var res = filterContext.HttpContext.Response;
           res.StatusCode = 401;
           res.AddHeader("WWW-Authenticate", "Basic realm=\"Twitter\"");
           res.End();
       }
   }
}

そして、コントローラーのアクション:

[RequireBasicAuthentication]
public ActionResult Index() {
    var cred = System.Text.ASCIIEncoding.ASCII
            .GetString(Convert.FromBase64String(
            Request.Headers["Authorization"].Substring(6)))
            .Split(':');
    var user = new { Name = cred[0], Pass = cred[1] };
    return Content(String.Format("user:{0}, password:{1}", 
        user.Name, user.Pass));
}

このアクションにより、入力したユーザー名とパスワードが正常に出力されます。しかし、私はそれがこれを行うための最良の方法であるとは本当に疑っています。この方法でユーザー名とパスワードを要求する以外に選択肢はありませんか?

于 2009-10-22T14:17:14.090 に答える
3

答えを修正して、ロジック全体をカスタム 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;
        }
        var res = filterContext.HttpContext.Response;
        res.StatusCode = 401;
        res.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
        res.End();
    }
}

コントローラー全体を基本認証の下に置くために使用できます。

[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() 
    {
        ...
    }
}

: 上記の実装では、開発者はユーザー名とパスワードを ActionFilter の必須パラメーターとして手動で挿入する必要がありますが、簡単に拡張して任意の承認メカニズム (MembershipProvider、ASP.NET ID、外部 DBMS またはファイルのカスタム ユーザーベースなど) をサポートすることができます。 ) カスタム コンストラクターを削除し、それに応じて OnActionExecuting メソッドの IF ブロックを変更します。

追加情報については、私がブログに書いたこの投稿を読むこともできます。

于 2014-12-07T23:04:22.437 に答える
3

私が読んだ内容に基づいて、あなたは本当にサービスを作成したいのであって、Web アプリケーションではありません。私はここで推測していますが、ASP.NET MVC を選択してルーティングを利用し、URL を希望どおりに構築したと思いますか? 私が間違っている場合は修正してください。

私の意見では、あなたが抱えている問題を解決する最善の方法は、データを返す場合、WCF を使用して RESTful Web サービスを構築することです。この記事は、このルートに進みたい場合の開始に役立つはずです。

それ以外の場合は、リクエストを処理して認証するために、スタックをさらに上に移動する必要があります。その場合は、より多くの情報とコードを提供できるようお手伝いいたします。

于 2009-10-22T15:28:19.110 に答える
2

これが私のために働いた方法です。少し手間がかかりますが、IIS と MVC3 が Apache などの他のすべての基本的な HTTP 認証システムと同じように動作するようになります...

ステップ1。

IIS に「基本認証」がインストールされていることを確認します。

(例: コントロール パネル -> プログラムと機能 -> Windows の機能の有効化または無効化)

*現在 Windows 7 を使用しており、正確なパスがわかりません。[GOOGLE: IIS に基本認証をインストールする] を参照してください。

ステップ2。

サイトで基本認証が有効になっていることを確認します。前の手順でこれをインストールする必要があった場合は、IIS サービスをリセットし、すべてのアプリ プールが実際にダウンしたことを確認する必要があります。

ステップ 3。

(注: 私は MVC3 を使用していますが、これは大騒ぎせずに ASP.Net を含むほとんどのモデルで機能するはずです。)
プロジェクトでは、次のクラスを追加する必要があります。

public class ServicePrincipal : IPrincipal { // This answers the "What am I allowed to do" question

  // In real life, this guy will contain all your user info
  // and you can put what ever you like and retrieve it 
  // later via the HttpContext, on your application side.
  // Some fun with casting will be required.

  public static IPrincipal Default { 
    get {
      return new ServicePrincipal {
        Identity = new ServiceIdentity {
          AuthenticationType = "Test",
          IsAuthenticated = true,
          Name = "Basic"
        }
      };
    }
  }

  public IIdentity Identity { get; set; } 

  public bool IsInRole(string role) {
    // If you want to use role based authorization
    // e.g. [Authorize(Roles = "CoolPeople")]
    // This is the place to do it and you can do
    // anything from load info from a db or flat file
    // or simple case statement...though that would 
    // be silly.
    return true;
  }
}

public class ServiceIdentity : IIdentity { // This answers the "Who Am I" Question
  public string AuthenticationType { get; set; }

  public bool IsAuthenticated { get; set; }

  public string Name { get; set; }
}


public class ServiceModule : IHttpModule { // This is the module for IIS
  public void Init(HttpApplication context) {
    context.AuthenticateRequest += this.BasicAuthenticationRequest;
  }

  public void BasicAuthenticationRequest(object sender, EventArgs e) {
    HttpApplication app = sender as HttpApplication;

    if( !ServiceProvider.Authenticate(app.Context) ) {
      // Total FAIL!
    }
  }

  public void Dispose() {
    // Clean up the mess, if needed.
  }

}

public class ServiceProvider {

  public static bool Authenticate( HttpContext context ) {
    // For the example we are going to create a nothing user
    // say he is awesome, pass him along through and be done.
    // The heavy lifting of the auth process will go here 
    // in the real world.

    HttpContext.Current.User = ServicePrincipal.Default;
    return true;
  }  
}

ステップ 3a。[編集]

「使用」するさまざまなライブラリを次に示します。

using System.Security.Principal;
using System.Web;

それらを入れたかっただけです。人々がそれらを除外するのは嫌いです。:)

ステップ 4。

以下を Web 構成に追加します。「構成」タグなど、周囲の構造を含めていることに注意してください...これは単なるロードマップです。既に「構成」タグがある場合は、他のタグを追加しないでください。そうしないと、IIS が怒ってしまいます。

<configuration>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="ServiceCredentialModule" type="{Namespace}.ServiceModule"/>
    </modules>
  </system.webServer>
<configuration>

{Namespace}.ServiceModule の Namespace は、ステップ 3 のクラスを配置した Namespace であることに注意してください。

...そして、それはほとんどそれです。

于 2012-04-09T19:30:21.950 に答える