Asp.net 使用.NET技术通过自定义授权进行UI到Web服务的通信
我正试图设计一个web应用程序,使用WCF服务访问数据并提供业务逻辑。因此,总体而言,整个系统将如下所示: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身份验证 应用程序必须提供身份验
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会话获取的用户数据进行扩展
- 该调用调用的服务方法将能够接收该用户数据,并根据用户权限使用它来提供结果
- 所有这些都会在后台发生,所以不会向从服务公开的每个服务方法添加额外的
method参数UserDetails
我读了很多关于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方法一样简单。