0

我正在尝试设计一个 Web 应用程序,该应用程序将使用 WCF 服务来访问数据并提供业务逻辑。所以总的来说,整个系统看起来像这样:

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向从 Service 公开的每个 Service Method 添加额外的方法参数。

我阅读了很多关于 WCF 本身的内容,但发现了任何可以满足我要求的内容。我希望我只是错过了它,它仍然是可能的。

4

2 回答 2

0

以纯格式将用户角色从客户端传递到服务器将是一个设计错误。客户端可以通过在应用程序范围之外自由调用它们来轻松滥用您的服务。

为什么不依赖角色提供者?这样,您从客户端传递的只是身份(甚至可以是表单 cookie),然后在服务器端读取所有角色。您甚至可以使用内置机制在角色 cookie 中缓存角色。

前段时间我写了两篇关于使用表单身份验证保护 wcf 的教程,以便网页和活动客户端之间的集成很容易

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 回答
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 以防止标准的 AuthorizationPolicy 覆盖 Thread.CurrentPrincipal:

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 回答