我对 WCF 开发相当陌生,在学习该框架时遇到了一些问题。我有一个必须支持 REST 和 SOAP 的服务 API。到目前为止,这很容易实现,尤其是使用 WCF4 和路由。
我目前正在研究授权,并通过创建两个新的管理器类来扩展 AuthorizationManager:“ApiKeyAuthorizationManager”和“ApiKeyAndTokenAuthorizationManager”
我的大多数服务都需要 ApiKey 和令牌 (GUIDS);初始身份验证时,您只需要有效的 ApiKey 和密码即可接收 Token。
到目前为止,REST 工作得很好,因为授权管理器会通过查询字符串来获取 ApiKey 和/或令牌。
例如,服务 uri 如下所示:
*http://api.domain.com/Service/Operation/ http://api.domain.com/Service/Operation/{someVariableValue}?ApiKey=GUID&Token=GUID
我现在的问题是授权 SOAP 服务调用。我做了一些研究,并得出了一些结论,我想在实施之前验证其正确性。
为了使用自定义凭据授权 SOAP,我应该:
- 创建自定义服务令牌(MSDN http://msdn.microsoft.com/en-us/library/ms731872.aspx)
- 通过创建自定义 SecurityTokenProvider、SecurityTokenAuthenticator 和 SecurityTokenSerializer 来扩展 WCF(MSDN http://msdn.microsoft.com/en-us/library/ms730868.aspx)
- 通过创建自定义授权策略来扩展 WCF (MSDN http://msdn.microsoft.com/en-us/library/ms751416.aspx)
我是否走在正确的道路上?所有这些步骤都需要适合我的场景吗?似乎只是为了验证由两个 GUID 组成的凭证而进行了如此多的定制。
Thanks!
[编辑#1]
这是一项非常艰巨的任务。自定义凭证和安全令牌几乎没有记录。事实证明,找到高质量的博客文章本身几乎是不可能的。我一直在努力,很快就找到了可行的解决方案。我什至遇到了与中描述的相同的障碍这个帖子 https://stackoverflow.com/questions/563037/wcf-authentication-with-custom-clientcredentials-what-is-the-clientcredentialtyp.
当我尝试访问我的服务以发现 wsdl 或 mex 时,我收到此错误:
The service encountered an error.
An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.InvalidOperationException: An exception was thrown in a call to a policy export extension.
Extension: System.ServiceModel.Channels.SymmetricSecurityBindingElement
Error: Specified argument was out of the range of valid values.
Parameter name: parameters ----> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: parameters
at System.ServiceModel.Security.WSSecurityPolicy.CreateTokenAssertion(MetadataExporter exporter, SecurityTokenParameters parameters, Boolean isOptional)
at System.ServiceModel.Security.WSSecurityPolicy.CreateWsspSignedSupportingTokensAssertion(MetadataExporter exporter, Collection`1 signed, Collection`1 signedEncrypted, Collection`1 optionalSigned, Collection`1 optionalSignedEncrypted)
at System.ServiceModel.Security.WSSecurityPolicy.CreateWsspSupportingTokensAssertion(MetadataExporter exporter, Collection`1 signed, Collection`1 signedEncrypted, Collection`1 endorsing, Collection`1 signedEndorsing, Collection`1 optionalSigned, Collection`1 optionalSignedEncrypted, Collection`1 optionalEndorsing, Collection`1 optionalSignedEndorsing, AddressingVersion addressingVersion)
at System.ServiceModel.Security.WSSecurityPolicy.CreateWsspSupportingTokensAssertion(MetadataExporter exporter, Collection`1 signed, Collection`1 signedEncrypted, Collection`1 endorsing, Collection`1 signedEndorsing, Collection`1 optionalSigned, Collection`1 optionalSignedEncrypted, Collection`1 optionalEndorsing, Collection`1 optionalSignedEndorsing)
at System.ServiceModel.Channels.SecurityBindingElement.ExportSymmetricSecurityBindingElement(SymmetricSecurityBindingElement binding, MetadataExporter exporter, PolicyConversionContext policyContext)
at System.ServiceModel.Channels.SecurityBindingElement.ExportPolicy(MetadataExporter exporter, PolicyConversionContext context)
at System.ServiceModel.Description.MetadataExporter.ExportPolicy(ServiceEndpoint endpoint)
--- End of inner ExceptionDetail stack trace ---
at System.ServiceModel.Description.ServiceMetadataBehavior.MetadataExtensionInitializer.GenerateMetadata()
at System.ServiceModel.Description.ServiceMetadataExtension.EnsureInitialized()
at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.InitializationData.InitializeFrom(ServiceMetadataExtension extension)
at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.GetInitData()
at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.TryHandleDocumentationRequest(Message httpGetRequest, String[] queries, Message& replyMessage)
at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.ProcessHttpRequest(Message httpGetRequest)
at SyncInvokeGet(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)