如何限制对 WCF 中某些方法的访问?

Posted

技术标签:

【中文标题】如何限制对 WCF 中某些方法的访问?【英文标题】:How do I restrict access to some methods in WCF? 【发布时间】:2012-07-18 22:52:16 【问题描述】:

开始使用简单的 WCF 服务时我有点迷茫。我有两种方法,我想向世界公开一种,另一种我想限制给某些用户。最终我希望能够使用客户端应用程序来使用受限方法。到目前为止,我可以匿名访问这两种方法:

C# 代码

namespace serviceSpace

    [ServiceContract]
    interface ILocationService
    
        [OperationContract]
        string GetLocation(string id);

        [OperationContract]
        string GetHiddenLocation(string id);
    

    [AspNetCompatibilityRequirements(
     RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class LocationService : ILocationService
    
        [WebGet(UriTemplate = "Location/id")]
        public string GetLocation(string id)
        
            return "O hai, I'm available to everyone.";
        

        // only use this if authorized somehow
        [WebGet(UriTemplate = "Location/hush/id")]
        public string GetHiddenLocation(string id)
        
            return "O hai, I can only be seen by certain users.";
        


    

配置

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>    
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" 
          automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>

我该如何开始?

【问题讨论】:

我认为这个问题的答案是一种可能的方法。 ***.com/questions/4641442/… 【参考方案1】:

我找到的很多答案几乎都是我需要的,但并不完全正确。我最终设置了 ASP.net 成员资格并实现了一个自定义属性来提取授权标头并在请求进入时处理登录。所有的魔法都发生在 BeforeCallParseAuthorizationHeader 下面:

public class UsernamePasswordAuthentication : Attribute, IOperationBehavior, IParameterInspector

    public void ApplyDispatchBehavior(OperationDescription operationDescription,
        DispatchOperation dispatchOperation)
    
        dispatchOperation.ParameterInspectors.Add(this);
    

    public void AfterCall(string operationName, object[] outputs,
                          object returnValue, object correlationState)
    
    

    public object BeforeCall(string operationName, object[] inputs)
    
        var usernamePasswordString = parseAuthorizationHeader(WebOperationContext.Current.IncomingRequest);
        if (usernamePasswordString != null)
        
            string[] usernamePasswordArray = usernamePasswordString.Split(new char[]  ':' );
            string username = usernamePasswordArray[0];
            string password = usernamePasswordArray[1];
            if ((username != null) && (password != null) && (Membership.ValidateUser(username, password)))
            
                Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username), new string[0]);
                return null;
            
        

        // if we made it here the user is not authorized
        WebOperationContext.Current.OutgoingResponse.StatusCode =
            HttpStatusCode.Unauthorized;
        throw new WebFaultException<string>("Unauthorized", HttpStatusCode.Unauthorized);            
    

    private string parseAuthorizationHeader(IncomingWebRequestContext request)
    
        string rtnString = null;
        string authHeader = request.Headers["Authorization"];
        if (authHeader != null)
        
            var authStr = authHeader.Trim();
            if (authStr.IndexOf("Basic", 0) == 0)
            
                string encodedCredentials = authStr.Substring(6);
                byte[] decodedBytes = Convert.FromBase64String(encodedCredentials);
                rtnString = new ASCIIEncoding().GetString(decodedBytes);
            
        
        return rtnString;
    

    public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    
    

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    
    

    public void Validate(OperationDescription operationDescription)
    
    


从那里我只需要将我的新属性添加到服务合同条目中。对该方法的任何请求都需要有效的授权标头,否则将在进行任何进一步处理时发回 Not Authorized 响应。

[ServiceContract]
interface ILocationService

    [OperationContract]
    string GetLocation(string id);

    [OperationContract]
    [UsernamePasswordAuthentication]  // this attribute will force authentication
    string GetHiddenLocation(string id);

【讨论】:

+1。感谢您提供此代码。我尝试使用它,得到“System.ServiceModel.FaultException`1 未被用户代码处理”,但我使用this 解决了它,现在它可以工作了。【参考方案2】:

使用以下步骤限制特定 Windows 用户的访问:

打开计算机管理 Windows 小程序。 创建一个包含您希望授予访问权限的特定 Windows 用户的 Windows 组。例如,可以将一个组称为“CalculatorClients”。 将您的服务配置为要求 ClientCredentialType = “Windows”。这将要求客户端使用 Windows 身份验证进行连接。 使用 PrincipalPermission 属性配置您的服务方法,以要求连接用户是 CalculatorClients 组的成员。
// Only members of the CalculatorClients group can call this method.
[PrincipalPermission(SecurityAction.Demand, Role = "CalculatorClients")]
public double Add(double a, double b)
 
return a + b; 

【讨论】:

以上是关于如何限制对 WCF 中某些方法的访问?的主要内容,如果未能解决你的问题,请参考以下文章

C++:有没有办法在不暴露其他私有成员的情况下限制对某些类的某些方法的访问?

如何限制对 Access 中某些列的访问

如何限制对当前文件的某些功能或对象的访问?

使用 FolderBrowserDialog 限制对某些文件夹的访问

如何限制对Web API 2应用程序中的已知客户端应用程序的API访问?

Laravel 4 身份验证。限制对资源的某些功能的访问,但不是全部