15

単純なWCFサービスを使い始めるのに少し迷っています。私には2つの方法があり、1つを世界に公開し、もう1つを特定のユーザーに限定したいと思います。最終的には、クライアントアプリケーションを使用して制限付きメソッドを使用できるようにしたいと考えています。これまでのところ、匿名で両方のメソッドにアクセスできます。

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>

どうすれば始められますか?

4

2 に答える 2

11

私が見つけた多くの答えは、ほとんど私が必要としていたものでしたが、完全には正しくありませんでした. 最後に、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);
}
于 2012-09-26T15:31:28.600 に答える
3

次の手順を使用して、特定のWindowsユーザーへのアクセスを制限します。

  • ComputerManagementWindowsアプレットを開きます。
  • アクセスを許可する特定のWindowsユーザーを含むWindowsグループを作成します。たとえば、グループは「CalculatorClients」と呼ぶことができます。
  • ClientCredentialType =“ Windows”を要求するようにサービスを構成します。これには、クライアントがWindows認証を使用して接続する必要があります。
  • 接続ユーザーがCalculatorClientsグループのメンバーである必要があるように、PrincipalPermission属性を使用してサービスメソッドを構成します。
// 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; 
}
于 2012-07-19T17:43:37.690 に答える