wcf数据合同授权

tah*_*ala 4 authentication wcf authorization

如何[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]在类上使用属性?

我正在寻找一些限制访问我的对象的方法,即如果在服务方法中访问某个对象,并且如果用户有权访问服务方法但没有权限访问该对象,则应抛出异常

Res*_*ing 5

PrincipalPermission属性可以装饰方法或类.因此,可以限制对对象实例的访问.有几件事需要做:

  1. 配置所选服务和客户端绑定以使用安全性.指定Windows为客户端凭据类型.
  2. 配置服务以使用Windows组进行授权.
  3. Adorn类将包含带PrincipalPermission属性的机密信息.

如果需要将singleton实例传递给ServiceHost构造函数,请执行以下操作:

  1. 创建服务单例实例.Thread.CurrentPrincipal必须具有访问机密对象所需的权限.
  2. ServiceHost通过传递服务单例实例来创建实例.属性InstanceContextModeServiceBehavior属性必须设置为InstanceContextMode.Single.

除此以外:

  1. ServiceHost通过传递服务类型来创建实例.

可选地,用FaultContract属性装饰服务方法并FaultException从中抛出以避免错误客户端通道.

这是一个例子:

服务配置文件:

<system.serviceModel>
    <services>
        <service name="Server.Service" behaviorConfiguration="Authorization">
            <endpoint address=""
                      binding="netTcpBinding" bindingConfiguration="TCP"
                      contract="Common.IService" />
            <host>
                <baseAddresses>
                    <add baseAddress="net.tcp://localhost:13031/Service"/>
                </baseAddresses>
            </host>
        </service>
    </services>
    <bindings>
        <netTcpBinding>
            <binding name="TCP" openTimeout="00:30:00" closeTimeout="00:00:10" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
                <security mode="Message">
                    <message clientCredentialType="Windows" />
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="Authorization">
                <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

客户端配置文件:

<system.serviceModel>
    <client>
        <endpoint name="NetTcpBinding_IService"
                  address="net.tcp://localhost:13031/Service"
                  binding="netTcpBinding" bindingConfiguration="TCP"
                  contract="Common.IService" />
    </client>
    <bindings>
        <netTcpBinding>
            <binding name="TCP" openTimeout="00:30:00" closeTimeout="00:00:10" sendTimeout="00:30:00" receiveTimeout="00:30:00" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
                <security mode="Message">
                    <message clientCredentialType="Windows" />
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

机密信息类:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators" ) ]
public class ContactInfo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ContactInfo()
    {
        FirstName = "John";
        LastName = "Doe";
    }
    public override string ToString()
    {
        return string.Format( "{0} {1}", FirstName, LastName );
    }
}
Run Code Online (Sandbox Code Playgroud)

服务合同及其实施:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [FaultContract( typeof( string ) )]
    string GetName( int id );
}

[ServiceBehavior]
// Use following if singleton instance needs to be passed to `ServiceHost` constructor
//[ServiceBehavior( InstanceContextMode = InstanceContextMode.Single )]
public class Service : IService
{
    private Dictionary<int, ContactInfo> Contacts { get; set; }
    public Service()
    {
        Contacts = new Dictionary<int, ContactInfo>();
        IPrincipal originalPrincipal = Thread.CurrentPrincipal;
        try
        {
            Thread.CurrentPrincipal = new WindowsPrincipal( WindowsIdentity.GetCurrent() );
            Contacts.Add( 1, new ContactInfo() );
        }
        finally
        {
            Thread.CurrentPrincipal = originalPrincipal;
        }
    }
    public string GetName( int id )
    {
        if ( Contacts.Count < id )
            return null;
        try
        {
            return Contacts[ id ].ToString();
        }
        catch ( Exception ex )
        {
            throw new FaultException<string>( ex.Message );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)