1

ASP.NET MVC アプリケーション内でホストされている WCF サービスがあります ( http://msdn.microsoft.com/en-us/library/aa702682.aspxで説明されています)。MVC アクションと WCF サービス操作の一部は保護されており、両方に ASP.NET フォーム認証を使用しています。

// protected MVC action
[Authorize]
public ActionResult ProtectedMvcAction(string args)

// protected WCF operation
[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void ProtectedWcfOperation(string args)

私の WCF クライアントは、.ASPXAUTHWCF 呼び出しのたびにフォーム認証 Cookie がサーバーに送信されるようにします。

これは長い間非常にうまく機能しました。HTTPS現在、証明書を使用してサーバーに暗号化を追加していますSSL。これにより、Web.config` に次の変更を加える必要がありました。

<basicHttpBinding>
  <binding name="ApiServiceBinding">
    <security mode="Transport">
      <transport clientCredentialType="None" />
    </security>
  </binding>
</basicHttpBinding>

サービスがアクティブになり、クライアントはサーバー操作を呼び出すことができます。ただし、[PrincipalPermission]保護されたサーバー操作の前にある属性により、すべてのサービス呼び出しが突然ブロックされます。私は次のことを知りました:

  • HTTP の場合 ( なし<security mode="Transport">)、 と の両方Thread.CurrentPrincipalがインスタンスにHttpContext.Current.User設定され、プロパティにインスタンスが含まれます。この場合、すべてが正常に機能します。RolePrincipalFormsIdentityRolePrincipal.Identity
  • HTTPS の場合 ( <security mode="Transport">web.config で)、プロパティHttpContext.Current.Userは引き続きRolePrincipal/FormsIdentity組み合わせに設定されます。しかし、プロパティThread.CurrentPrincipalが突然WindowsPrincipal/WindowsIdentityインスタンスに設定され、[PrincipalPermission]属性が例外をスローします。

私は次のことを試しました:

  • AppDomain.CurrentDomain.SetPrincipalPolicyをすべての可能な値 (Global.asaxの) に変更しましApplication_Startたが、何も変わりませんでした。
  • Thread.CurrentPrincipalプロパティを に設定しますが、と実際のサービス呼び出しの間Application_PostAuthenticateで、 が再びに変更されます。Application_PostAuthenticateThreadCurrentPrincipalWindowsPrincipal

ヒントはありますか?私は何を間違っていますか?

4

2 に答える 2

3

これはそれを解決します:

http://www.codeproject.com/Articles/304877/WCF-REST-4-0-Authorization-with-From-Based-authent

このコードを変更して、Windows と Forms のエンドポイントと同じサービスをカバーするようにしました (これも機能します)。

public bool Evaluate( EvaluationContext evaluationContext, ref object state )
{
    bool ret = false;
    // get the authenticated client identity
    HttpCookie formsAuth = HttpContext.Current.Request.Cookies[ ".MyFormsCookie" ];
    if( null != formsAuth )
    {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt( formsAuth.Value );
        if( null != ticket )
        {
            GenericIdentity client = new GenericIdentity( ticket.Name, "Forms" );

            // set the custom principal
            CustomPrincipal p = new CustomPrincipal( client );
            p.RoleManagerProvider = "Internet";
            evaluationContext.Properties[ "Principal" ] = p;

            ret = true;
        }
    }
    else
    {
        CustomPrincipal p = new CustomPrincipal( HttpContext.Current.User.Identity );
        p.RoleManagerProvider = "Intranet";
        evaluationContext.Properties[ "Principal" ] = p;

        // assume windows auth
        ret = true;

    }
    return ret;
}

フォーム認証 Cookie を探し、そこにない場合は Windows 認証を使用しようとします。また、内部および外部のロール プロバイダーを「反転」します

これにより、ユーザーの資格情報をインターネット (Cookie の転送による) およびイントラネット (Windows の制約付き委任を使用) から同じ内部サービスに伝達できます。

(サンプルごとのコードではなく)構成で構成を行いましたが、問題ないようです。

動作については、次のようなものです。

 <behavior name="FormsPaymentsBehavior">
          <serviceAuthorization principalPermissionMode="Custom" >
            <authorizationPolicies>
              <add policyType="FormsPolicy.AuthorizationPolicy,FormsPolicy" />
            </authorizationPolicies> 
          </serviceAuthorization>

FormsPolicy (上記) が両方を処理するため、これは両方のエンドポイントに使用され、エンドポイントごとに異なる動作を指定することはできません。

バインディングは、適切なエンドポイントで Windows 資格情報のハンドシェイクを強制します。

<basicHttpBinding>
        <binding name="WindowsHttpBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
        <binding name="FormsHttpBinding" allowCookies="true">          
          <security mode="None">
            <transport clientCredentialType="None" />            
          </security>
        </binding>
      </basicHttpBinding>

トランスポート モードを次のように変更できます。

<security mode="Transport">
            <transport clientCredentialType="None" />
          </security>

httpsの場合、正常に動作します。

カスタム プリンシパルについては、ロール マネージャーを明示的に呼び出す必要があることがわかりました

...


public bool IsInRole( string role )
        {
            RoleProvider p = Roles.Providers[ RoleManagerProvider ];
            return p.IsUserInRole( Identity.Name, role );
        }

        public String RoleManagerProvider { get; set; }

...

これは、私が aspnet 互換のものを使用しなくなったためだと思います。認証タイプに応じてロール マネージャーを切り替えているので、うーん。

于 2012-09-26T14:57:19.210 に答える
1

私もこの問題を経験しており、ここに別のレポート (および私のもの) があります。http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8f424d4f-2f47-4f85-a6b0-00f7e58871f1/

このスレッドは、カスタム承認ポリシー (http://msdn.microsoft.com/en-us/library/ms729794.aspx) とこのコード プロジェクト記事 (http://www.codeproject. com/Articles/304877/WCF-REST-4-0-Authorization-with-From-Based-authent) は、FormsAuth でこれを行う方法を正確に説明しているようです - EvaluationContext.Properties["Principal"] = new CustomPrincipal(client の設定) MS のコメントによる。

私はまだこれを実装していません - 私の「応急処置」は単純に昔ながらの asmx サービスに戻すことでした - しかし、いつか「試してみる」つもりです!

別の解決策を見つけた場合は、お知らせください。

于 2012-07-18T11:19:24.253 に答える