Asp.net 使用.NET技术通过自定义授权进行UI到Web服务的通信

Asp.net 使用.NET技术通过自定义授权进行UI到Web服务的通信,asp.net,wcf,authorization,soa,Asp.net,Wcf,Authorization,Soa,我正试图设计一个web应用程序,使用WCF服务访问数据并提供业务逻辑。因此,总体而言,整个系统将如下所示: UI (ASP.NET MVC) BusinessLayer (WCF Services) DataLayer (Entity Framework) Date (SQL Server Database) 系统的所有部分都将在相同的封闭环境中进行抵抗,因此我将使用证书来保护ASP.NET WCF连接。数据库连接将使用标准EF安全性、连接字符串和Windows身份验证 应用程序必须提供身份验

我正试图设计一个web应用程序,使用WCF服务访问数据并提供业务逻辑。因此,总体而言,整个系统将如下所示:

UI (ASP.NET MVC)
BusinessLayer (WCF Services)
DataLayer (Entity Framework)
Date (SQL Server Database)
系统的所有部分都将在相同的封闭环境中进行抵抗,因此我将使用证书来保护
ASP.NET WCF
连接。数据库连接将使用标准EF安全性、连接字符串和Windows身份验证

应用程序必须提供身份验证和授权功能。我将把其中的大部分转移到ASP.NET中,因此将有
ValidateUserAuth()
service方法,它将用于验证凭据,但结果(用户所属的
UserRole
)将由ASP用于创建用户会话

在此之后,每个服务方法调用都需要知道当前用户的UserRole,以返回正确的结果(如果有必要,可以说“拒绝访问”)问题是我不想将
UserRole
作为每个服务方法的参数传递
我想让它自动发生。使用WCF是否可能

我只需要:

  • 从ASP.NET应用程序发出的每个服务调用都将使用从当前ASP会话获取的用户数据进行扩展
  • 该调用调用的服务方法将能够接收该用户数据,并根据用户权限使用它来提供结果
  • 所有这些都会在后台发生,所以不会向从服务公开的每个服务方法添加额外的
    UserDetails
    method参数

我读了很多关于WCF本身的书,但找到了任何可以满足我要求的东西。我希望我错过了它,而且它仍然是可能的。

以简单的形式将用户角色从客户端传递到服务器将是一个设计错误。客户端可以自由调用您的服务,从而很容易滥用您的服务,这超出了应用程序的范围

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

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


我决定使用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
我还必须设置自定义授权策略以防止标准策略覆盖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

WCF服务将关闭,所以不可能从互联网上直接呼叫。难道它不能使以普通形式传递的userId或userRole有效吗?我认为是一种请求伪造威胁,在这种情况下,api可能会滥用它。我认为无论是从internet还是从intranet调用api都无关紧要——您仍然不希望用户能够假装他们是管理员,就像调用带有特定纯参数组合的web方法一样简单。