wcf数据合同授权

时间:2011-02-19 13:45:46

标签: wcf authentication authorization

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

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

2 个答案:

答案 0 :(得分:5)

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

  1. 配置所选服务和客户端绑定以使用安全性。将Windows指定为客户端凭据类型。
  2. 配置服务以使用Windows组进行授权。
  3. Adorn课程,其中包含PrincipalPermission属性的机密信息。
  4. 如果需要将单例实例传递给ServiceHost构造函数,请执行以下操作:

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

      1. 通过传递服务类型来创建ServiceHost实例。
      2. 可选地,使用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>
        

        客户端配置文件

        <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>
        

        机密信息类

        [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 );
            }
        }
        

        服务合同及其实施

        [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 );
                }
            }
        }
        

答案 1 :(得分:1)

如果您熟悉.NET权限编码(命令式或声明式),则模式完全相同。在声明形式中,PrincipalPermissionAttribute应用于实现服务契约的类中的方法:

[PrincipalPermission(SecurityAction.Demand, Role = "Updaters")]
public bool Update()
{
return true;
}

在此示例中,检查当前主体以查看它是否属于名为Updaters的角色。在属性的实际实现中,调用主体上的IsInRole方法。

对于PrincipalPermissionAttribute的命令性确定,将创建PrincipalPermission类的实例。 PrincipalPermission的构造函数将用户名和角色作为参数。实例化时,可以调用Demand方法来确定当前主体是否具有必要的权限。以下代码提供了一个示例:

PrincipalPermission p = new PrincipalPermission(null, "Updaters");
p.Demand();

配置应如下所示:

<behaviors>
  <serviceBehaviors>
    <behavior>
      ...
      <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
    </behavior>
  </serviceBehaviors>
</behaviors>

对于工作样本,请查看:Authorizing Access to Service Operations