0

WCFサービスを使用してデータにアクセスし、ビジネスロジックを提供するWebアプリケーションを設計しようとしています。したがって、一般的に、システム全体は次のようになります。

UI (ASP.NET MVC)
BusinessLayer (WCF Services)
DataLayer (Entity Framework)
Date (SQL Server Database)

システムのすべての部分が同じ閉じた環境に抵抗するので、証明書を使用してASP.NET <-> WCF接続を保護します。データベース接続では、標準のEFセキュリティ、接続文字列、およびWindows認証が使用されます。

アプリケーションは、認証および承認機能を提供する必要があります。そのほとんどをASP.NETに移動するので、ValidateUserAuth()資格情報の検証に使用されるサービスメソッドがありますが、その結果(UserRoleそのユーザーが属する)はASPによってユーザーセッションの作成に使用されます。

その後、すべてのサービスメソッド呼び出しは、適切な結果を返すために、現在のユーザーのUserRoleを知る必要があります(または、必要に応じて「アクセスが拒否されました」と言います)。問題は、それをすべてのサービスメソッドのパラメータとして渡したくないということです。UserRole自動的に実現させたいのですが。WCFでも可能ですか?

必要なのは:

  • ASP.NETアプリから行われるすべてのサービス呼び出しは、現在のASPセッションから取得されたユーザーデータで拡張されます。
  • その呼び出しによって呼び出されたサービスメソッドは、そのユーザーデータを受け取り、それを使用してユーザーのアクセス許可に従って結果を提供することができます。
  • これはすべてバックグラウンドで発生するため、UserDetailsサービスから公開されるすべてのサービスメソッドに追加のメソッドパラメータが追加されることはありません。

私はWCF自体についてたくさん読みましたが、私の要件を満たすことができるものは何でも見つかりました。私はそれを逃しただけで、それはまだ可能だと思います。

4

2 に答える 2

0

そのために MessageInspector を使用することにしました。

クライアント側:

Public Function BeforeSendRequest(ByRef request As System.ServiceModel.Channels.Message, channel As System.ServiceModel.IClientChannel) As Object Implements System.ServiceModel.Dispatcher.IClientMessageInspector.BeforeSendRequest
    Dim requestMessageProperty = New HttpRequestMessageProperty()

    Dim currentUser = Authentication.AuthenticatedStaffcareUser

    If currentUser Is Nothing Then Throw New ApplicationException()

    requestMessageProperty.Headers("UserName") = currentUser.UserName
    requestMessageProperty.Headers("UserId") = currentUser.UserID
    requestMessageProperty.Headers("UserRole") = currentUser.UserRole
    requestMessageProperty.Headers("EffectiveDate") = currentUser.EffectiveDate
    request.Properties(HttpRequestMessageProperty.Name) = requestMessageProperty

    Return Nothing
End Function

そしてサーバー側:

Public Function AfterReceiveRequest(ByRef request As Message, channel As IClientChannel, instanceContext As InstanceContext) As Object Implements IDispatchMessageInspector.AfterReceiveRequest
    Dim messageProperty = CType(OperationContext.Current.IncomingMessageProperties(HttpRequestMessageProperty.Name), HttpRequestMessageProperty)

    Dim userName = messageProperty.Headers("UserName")
    Dim userId = Integer.Parse(messageProperty.Headers("UserId"))
    Dim userRole = messageProperty.Headers("UserRole")
    Dim effectiveDate = DateTime.Parse(messageProperty.Headers("EffectiveDate"))

    Dim identity = New AppServerUserIdentity(userName, userId, userRole, effectiveDate)
    Dim principal = New AppServerUserPrincipal(identity)

    Threading.Thread.CurrentPrincipal = principal

    Return Nothing
End Function

標準の AuthorizationPolicy が Thread.CurrentPrincipal を上書きしないように、カスタムの AuthorizationPolicy も設定する必要がありました。

Public Function Evaluate(evaluationContext As EvaluationContext, ByRef state As Object) As Boolean Implements IAuthorizationPolicy.Evaluate

    Dim principal = TryCast(Threading.Thread.CurrentPrincipal, AppServerUserPrincipal)

    If principal Is Nothing Then
        Return False
    Else
        evaluationContext.Properties("Principal") = principal
        Return True
    End If
End Function
于 2013-02-04T13:44:19.787 に答える
0

クライアントからサーバーにプレーンな形式でユーザーの役割を渡すことは、設計上の誤りです。クライアントは、アプリケーションの範囲外でサービスを自由に呼び出して、簡単に悪用する可能性があります。

ロール プロバイダーに頼ってみませんか? このように、クライアントから渡されるのは ID (フォーム Cookie の場合もあります) だけであり、サーバー側ですべてのロールを読み取ります。組み込みのメカニズムを使用して、ロール Cookie にロールをキャッシュすることもできます。

少し前に、フォーム認証による wcf セキュリティ保護に関する 2 つのチュートリアルを書き、Web ページとアクティブなクライアントとの統合を容易にしました。

http://netpl.blogspot.com/2008/02/clickonce-webservice-and-shared-forms.html

http://netpl.blogspot.com/2010/04/aspnet-forms-authentication-sharing-for.html

于 2013-01-27T12:41:48.863 に答える