3

userNamePasswordValidationMode次のように、WCF アプリにカスタムを実装しました。

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding>
                <security mode ="Message">
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="True"/>
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyProject.Validator.MyValidator, MyProject" />
                </serviceCredentials>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
</system.serviceModel>

これはエラーをスローしませんが、クライアントでサービスを参照してユーザー名とパスワードの資格情報を設定すると、間違ったパスワードを入力してもメソッドが呼び出されます。

Testing.myAPIClient.client = new Testing.myAPIClient();
client.ClientCredentials.UserName.UserName = "test";
client.ClientCredentials.UserName.Password = "wrongpassword";

Console.WriteLine(client.StockQuery("123"));
Console.ReadLine();

メソッドStockQueryは引き続き呼び出され、コードは呼び出されMyValidatorません。

public class MyValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            using (var ax = new AXConnector())
            {
                if (!(bool)ax.CallStaticClassMethod("OnlineUsers", "validateLogon", userName, password))
                {
                    throw new UnauthorizedAccessException("Not Authorised");
                }
            }
        }
    }

編集

ここに私のapp.configがあります:

    <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IMyAPI" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://myServer:89/MyAPI.svc" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IMyAPI" contract="Testing.IMyAPI"
            name="BasicHttpBinding_IMyAPI" />
    </client>
</system.serviceModel>

編集 2

サービス インターフェイス:

[ServiceContract]
public interface IMyAPI
{
    string UserName { [OperationContract] get; [OperationContract] set; }
    string Password { [OperationContract] get; [OperationContract] set; }

    [OperationContract]
    bool StockQuery(string partNo);

    [OperationContract]
    decimal PriceQuery(string partNo, string accNo);
}

サービス クラス:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required),
ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class MyAPI : IMyAPI
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public MyAPI()
    {
        this.CheckSecurity();
    }

    private void CheckSecurity()
    {
        if (this.UserName != "test" && this.Password != "123")
        {
            throw new UnauthorizedAccessException("Not Authorised");
        }
    }

    // StockQuery and PriceQuery methods...
}
4

2 に答える 2

1

クライアントは、あるべき場所にSecurity.Mode設定されています。"None""Message"

<security mode ="Message">
    <message clientCredentialType="UserName"/>
</security>

編集:それを使用するには証明書が必要な場合があります。このウォークスルーに従うことはできますが、本番環境で使用することはお勧めしません。

[1]別のオプションは、独自のセキュリティを実装することです。これが基本的な例です。

WCFサービス

あなたのサービスでは、それServiceBehaviorInstanceContextModePerSessionConcurrencyMode変更しますSingle

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class SomeService : ISomeService
{ 
    // ...
}

UsernameサービスにPasswordプロパティを追加します。

public string UserName { [OperationContract] get; [OperationContract] set; }
public string Password { [OperationContract] get; [OperationContract] set; }

セキュリティをチェックするためのプライベートメソッドを追加します。

public void CheckSecurity()
{
    if ((this.UserName == null || this.Password == null) ||
        this.UserName == "username" && this.Password == "password"))
    {
        throw new FaultException("Unknown username or incorrect password.");
    }
}

CheckSecurity次に、各サービスのメソッドを呼び出します[2]クラスコンストラクタ方法。

public void SomeServiceMethod()
{
    this.CheckSecurity();
    // some method code
}

クライアントアプリケーション

クライアントアプリケーションコードで、すべてのインスタンスにサービスのユーザー名とパスワードを設定するか、これを行う静的クラスを作成します。

また、セキュリティを強化するために、ユーザー名とパスワードに暗号化を使用することもできます。

[1] WCFサービスにパスワードを設定する方法の私の答えから引用[2]各サービスメソッドの先頭でメソッド
を呼び出す必要があります。CheckSecuirty

于 2012-04-18T08:34:44.740 に答える