1

注: 以下のコード コメントには多くの質問が散らばっています。それらへの回答も必要です。

私は(他の多くの記事の中でも)次の記事を読みました。

Authorization ヘッダーを使用して、Web API の認証をヘッダーで送信したいと考えています。このヘッダーを と呼ばれる ac# クラスに入力したいと思いAuthenticationTokenます。次に、パラメーター バインディングを行っているときに、以前に作成したこのAuthenticationTokenオブジェクトを取得し、それをコントローラー アクションに渡したいと思います。たとえば、次のコントローラーがある場合

public class MyServiceController : ApiController {

    readonly ISecurityService _security;
    readonly IMyService _myService;

    // constructor values are injected
    public MyServiceController(ISecurityService security, IMyService myService) {
        _security = security;
        _myService = myService;
    }

    public SomeData GetASpecificItem(AuthenticationToken token, int id) {

       if (_security.IsAuthorized(token, Permissions.Read)) {
           return myService.DoStuffToGetSomeData(token);
       } else {
          var msg = new HttpResponseMessage(HttpStatusCode.Forbidden);
          throw new HttpResponseException(msg);
       }
    }
}

および次のパラメータ バインディング クラス

public class AuthenticationTokenParameterBinding 
  : HttpParameterBinding { // do I need to inherit from a different class?

  public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider,
                                           HttpActionContext actionContext,
                                           CancellationToken cancellationToken) {
    try {

      AuthenticationToken token; // UPDATED: how can i get this from the data 
                                 //          available from inside this method?

      SetValue(actionContext, token);

      // is this the correct task to return on successfull parameter binding?
      return base.ExecuteBindingAsyn(metadataProvider, actionContext, cancellationToken);

    } catch {
      return Task<HttpResponseMessage>.Factory.StartNew(() => {
        var hpm = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        hpm.Headers.Add("WWW-Authenticate","MyCustomScheme");
        return hpm;
      });
    }
  }
}

AuthenticationTokenこれら 2 つが正しく実装されている場合、コントローラーは承認時に作成されたインスタンスを自動的に取得します。

このプロセスの前に認証する場所がわかりません。また、認証と承認の間でオブジェクトを渡す方法もわかりません。

更新:AuthorizeAttribute承認がオブジェクトに反する可能性があるため 、カスタムを使用できません:

public SaveResponse Save(AuthenticationToken user, SomeObjectThatNeedsToBeSaved obj) {

  // NOTE: permissions are checked between the object and the user, not a role

  if (_security.IsAuthorized(user, obj, Permission.Modify, Permission.Create)) {

     // NOTE: other permissions we don't know about may need to be checked in the service call

     return new SaveResponse {
         Success = ISomeService.Save(user, obj); // bool return value
     }
  } else {
     // return 403 Forbidden      }
}

コントローラー アクションにトークンを渡す必要がありますが、コントローラーに渡される前にトークンを認証する必要もあります。これらすべてが必ずしもロールベースであるとは限らないため、カスタム内から認証する方法がわかりませんAuthorizeAttribute

4

1 に答える 1

1

カスタムAuthorizeAttributeを使用して、Web API の認証と承認の両方を処理しました。この属性はフィルターとして機能し、Web API メソッドに到達する前に要求を処理します。オーバーライドされたOnAuthorizeメソッドでは、認証が失敗した場合はHttpResponseMessage(System.Net.HttpStatusCode.Unauthorized)を返し、承認が失敗した場合はHttpResponseMessage (System.Net.HttpStatusCode.Forbidden) を返すことができるため、クライアントは両方のタイプのエラーを区別できます。カスタムのAuthorizeAttributeに加えて、カスタムのMembershipProviderRoleProviderを実装して、特定のセキュリティ要件とカスタムのデータベース スキーマを処理しました。

基本認証を使用して、承認用の資格情報を渡します。これにより、資格情報がヘッダーに配置されます。これを行うには、JQuery ajax関数のbeforeSendイベント ハンドラーを使用すると非常に簡単です。これを行う方法の例を次に示します。

    getAuthorizationHeader = function (username, password) {
      var authType;
      var up = $.base64.encode(username + ":" + password);
      authType = "Basic " + up;
    };
    return authType;
 };

    $.ajax({
        url: _url,
        data: _data,
        type: _type,
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", getAuthorizationHeader(username, password));
        },
        success: ajaxSuccessHandler,
        error: ajaxErrHandler
    });

これは、ヘッダーで送信されるユーザー名/パスワードをエンコードします。エンコードは簡単にデコードできるため、エンコードだけに頼るには十分なセキュリティではないことに注意してください。ネットワーク経由で送信される情報が安全であることを確認するために、引き続き HTTPS/SSL を使用する必要があります。

Web API 側では、ヘッダーから資格情報を取得してデコードし、承認プロセスを実行するカスタムAuthorizeAttributeを作成できます。コントローラーとは対照的に、Web API によって使用される別のAuthorizeAttributeがあります。カスタムAuthorizeAttributeを作成するときは、必ずSystem.Web.Http.AuthorizeAttributeを基本クラスとして使用してください。それらは異なる動作をします。コントローラー用のものはログオン ページにリダイレクトする必要がありますが、Web API 用のものは成功または失敗を示す HTTP コードを返します。クライアントがそれに応じて反応できるように、認証ではなく認証による失敗を認証が区別できない場合は、Forbidden の HTTP コードを返します。

カスタムAuthorizeAttributeで使用できるヘッダーから認証情報を取得する方法の例を次に示します。

    private bool GetUserNameAndPassword(HttpActionContext actionContext, out string username, out string password)
    {
        bool gotIt = false;
        username = string.Empty;
        password = string.Empty;
        IEnumerable<string> headerVals;
        if (actionContext.Request.Headers.TryGetValues("Authorization", out headerVals))
        {
            try
            {
                string authHeader = headerVals.FirstOrDefault();
                char[] delims = { ' ' };
                string[] authHeaderTokens = authHeader.Split(new char[] { ' ' });
                if (authHeaderTokens[0].Contains("Basic"))
                {
                    string decodedStr = SecurityHelper.DecodeFrom64(authHeaderTokens[1]);
                    string[] unpw = decodedStr.Split(new char[] { ':' });
                    username = unpw[0];
                    password = unpw[1];
                }
                gotIt = true;
            }
            catch { gotIt = false; }
        }

        return gotIt;
    }

そして、このメソッドで使用されるヘッダー データをデコードするためのコードを次に示します。

    public static string DecodeFrom64(string encodedData)
    {

        byte[] encodedDataAsBytes

            = System.Convert.FromBase64String(encodedData);

        string returnValue =

           System.Text.Encoding.ASCII.GetString(encodedDataAsBytes);

        return returnValue;

    }

ユーザー名とパスワードを取得したら、承認プロセスを実行し、処理のために適切な HTTP コードをクライアントに返すことができます。

カスタムトークンを使用して同様のプロセスを実行するか、クライアントにパスワード/ユーザー名を保存したくない場合は、やり取りされる Cookie を利用できます。

于 2013-01-17T18:19:36.933 に答える