3

ASP.NET MVC 4 Web アプリケーションの領域に REST API を作成しました。API は正常に動作しており、セキュリティを確保したいと考えています。

これを行う方法の非常に簡単な例はありますか? DotNetOpenAuth のダウンロードに付属のサンプルを調べていますが、完全に理解できません。

4

1 に答える 1

9

私は数日前に同じ問題を抱えていました。この答えはとてつもなく長いです。おそらくもっと簡単な方法があります。

個人的には、DNOA は自己検証 (つまり、暗号化されたトークン) 向けに設計されているため、要求ごとに DB をヒットする必要がないため、もう使用していません。これの非常に重要な副作用は、アクセスの取り消しがすぐに有効になるのではなく、トークンを更新する必要がある場合にのみ有効になることです。また、アクセス トークンは非常に長くなります (約 500 バイト)。

最初のステップとして、必要なものを確認してください。


OAuth / OAuth2 は一見簡単に見えますが、承認ワークフローがどのように設計されているかを理解することが重要です。また、彼らの用語はイライラする可能性があります。たとえば、「クライアント」は、私が素朴にクライアントアプリケーションと呼ぶものを指します。ユーザー (OAuth 用語で「リソース所有者」と呼ばれる) ではありません。私の提案: RFC 6749を読んでください。退屈そうに見えますが、面白い読み物です (半分飛ばしても構いません...)。

重要な質問は、2-legged OAuth または 3-legged OAuth (またはその両方) が必要ですか? です。どの種類の助成金をサポートする必要がありますか?

基本的に HTTP 基本認証を置き換えたい場合は、単純な「リソース所有者のパスワード資格情報フロー」で十分です。「このアプリケーションに私のプロフィール情報にアクセスさせる」という facebook/twitter の種類のタイプは 3-legged OAuth です。

素敵な付与タイプの図が付属している IBM ドキュメントがあります。


DNOA を見てみましょうSamples/OAuthAuthorizationServer

適切なエントリ ポイントはOAuthController.csファイルです。AuthorizeおよびAuthorizeResponseアクションは、ユーザーがサードパーティ アプリケーション (3-legged OAuth) へのアクセスを許可できるようにする場合にのみ必要であることに注意してください。

2 つのシナリオでは、ユーザーは OAuthtokenエンドポイントに直接アクセスし、アクセス トークンを要求するだけです。いずれにしても、REST アプリケーションでそのようなコントローラーが必要になります。

内部の仕組みの鍵はOAuth2AuthorizationServerクラスです (クラスではありませんAuthorizationServer)。を見てくださいCode/OAuth2AuthorizationServer.cs。実装しIAuthorizationServerHostます。

そのクラスの半分はデータ ストレージ (別のデータストアで作業している場合は変更する必要があるかもしれません) を扱い、半分はアクセス トークンの暗号化を扱います。アプリケーションにも IAuthorizationServerHost を実装する必要があります。

#define SAMPLESONLYハードコーディングされた証明書を受け入れるように、コードに行があることを確認してください。

実際にリクエストを承認するには、カスタムActionFilterAttribute. これは、本番環境に対応していない、非常に凝縮されたコードです。

public sealed class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    private readonly OAuthResourceServer _authServer; 
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.Request.Headers.Authorization.Scheme == "Bearer"
            || actionContext.Request.Properties.ContainsKey("access_token"))
        {
            authenticatedUser = _authServer.VerifyOAuth2(request, required_claims);
            HttpContext.Current.User = authenticatedUser;
            Thread.CurrentPrincipal = authenticatedUser;
        }
    }
}

// See OAuthResourceServer/Code/OAuthAuthorizationManager.cs in DNOA samples
public sealed class OAuthResourceServer
{
    public IPrincipal VerifyOAuth2(HttpRequestMessage httpDetails, params string[] requiredScopes)
    {
        // for this sample where the auth server and resource server are the same site,
        // we use the same public/private key.
        using (var signing = CreateAuthorizationServerSigningServiceProvider())
        {
            using (var encrypting = CreateResourceServerEncryptionServiceProvider())
            {
                var tokenAnalyzer = new StandardAccessTokenAnalyzer(signing, encrypting);
                var resourceServer = new ResourceServer(_myUserService, tokenAnalyzer);
                return resourceServer.GetPrincipal(httpDetails, requiredScopes);
            }
        }
    }
}

リソース サーバーがまだ見つかりません

public sealed class MyResourceServer : ResourceServer
{
    public override System.Security.Principal.IPrincipal GetPrincipal([System.Runtime.InteropServices.OptionalAttribute]
        [System.Runtime.InteropServices.DefaultParameterValueAttribute(null)]
        HttpRequestBase httpRequestInfo, params string[] requiredScopes)
    {
        AccessToken accessToken = this.GetAccessToken(httpRequestInfo, requiredScopes);
        string principalUserName = !string.IsNullOrEmpty(accessToken.User)
            ? this.ResourceOwnerPrincipalPrefix + accessToken.User
            : this.ClientPrincipalPrefix + accessToken.ClientIdentifier;
        string[] principalScope = accessToken.Scope != null ? accessToken.Scope.ToArray() : new string[0];

        // Now your own code that retrieves the user 
        // based on principalUserName from the DB:
        return myUserService.GetUser(userName);
    }
}

次に、web.config を変更して、DNOA が開発中の SSL 接続の欠落について文句を言わないようにします。

<configSections>
      <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth">
        <section name="openid" type="DotNetOpenAuth.Configuration.OpenIdElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
        <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
        <sectionGroup name="oauth2" type="DotNetOpenAuth.Configuration.OAuth2SectionGroup, DotNetOpenAuth">
          <section name="authorizationServer" type="DotNetOpenAuth.Configuration.OAuth2AuthorizationServerSection, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
        </sectionGroup>
        <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
        <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
      </sectionGroup>    
  </configSections>
  <dotNetOpenAuth>
    <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
    <reporting enabled="true" />
    <openid>
      <provider>
        <security requireSsl="false">
        </security>
      </provider>
    </openid>
    <oauth2>
      <authorizationServer >
      </authorizationServer>
    </oauth2>
    <!-- Relaxing SSL requirements is useful for simple samples, but NOT a good idea in production. -->
    <messaging relaxSslRequirements="true">
      <untrustedWebRequest>
        <whitelistHosts>
          <!-- since this is a sample, and will often be used with localhost -->
          <add name="localhost"/>
        </whitelistHosts>
      </untrustedWebRequest>
    </messaging>
  </dotNetOpenAuth>
于 2013-02-16T12:14:05.867 に答える