Vorgehensweise: Erstellen einer benutzerdefinierten Prinzipalidentität

Das PrincipalPermissionAttribute ist ein deklaratives Mittel für die Steuerung des Zugriffs auf Dienstmethoden. Wenn Sie dieses Attribut verwenden, gibt die PrincipalPermissionMode-Enumeration den Modus für das Ausführen von Autorisierungsprüfungen an. Wenn dieser Modus auf PrincipalPermissionMode festgelegt ist, kann der Benutzer eine benutzerdefinierte IPrincipal-Klasse angeben, die von der CurrentPrincipal-Eigenschaft zurückgegeben wird. In diesem Thema wird das Szenario veranschaulicht, wenn PrincipalPermissionMode zusammen mit einer benutzerdefinierten Autorisierungsrichtlinie und einem benutzerdefinierten Prinzipal verwendet wird.

Weitere Informationen zur Verwendung von PrincipalPermissionAttribute finden Sie unter Vorgehensweise: Einschränken des Zugriffs mit der PrincipalPermissionAttribute-Klasse.

Beispiel

namespace CustomMode
{
    public class Test
    {
        public static void Main()
        {
            try
            {
                ShowPrincipalPermissionModeCustom ppwm = new ShowPrincipalPermissionModeCustom();
                ppwm.Run();

            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
                Console.ReadLine();
            }
        }
    }

    class ShowPrincipalPermissionModeCustom
    {
        [ServiceContract]
        interface ISecureService
        {
            [OperationContract]
            string Method1(string request);
        }

        [ServiceBehavior]
        class SecureService : ISecureService
        {
            [PrincipalPermission(SecurityAction.Demand, Role = "everyone")]
            public string Method1(string request)
            {
                return String.Format("Hello, \"{0}\"", Thread.CurrentPrincipal.Identity.Name);
            }
        }

        public void Run()
        {
            Uri serviceUri = new Uri(@"http://localhost:8006/Service");
            ServiceHost service = new ServiceHost(typeof(SecureService));
            service.AddServiceEndpoint(typeof(ISecureService), GetBinding(), serviceUri);
            List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>();
            policies.Add(new CustomAuthorizationPolicy());
            service.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();
            service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
            service.Open();

            EndpointAddress sr = new EndpointAddress(
                serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name));
            ChannelFactory<ISecureService> cf = new ChannelFactory<ISecureService>(GetBinding(), sr);
            ISecureService client = cf.CreateChannel();
            Console.WriteLine("Client received response from Method1: {0}", client.Method1("hello"));
            ((IChannel)client).Close();
            Console.ReadLine();
            service.Close();            
        }

        public static Binding GetBinding()
        {
            WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
            binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            return binding;
        }

        class CustomAuthorizationPolicy : IAuthorizationPolicy
        {
            string id = Guid.NewGuid().ToString();

            public string Id
            {
                get { return this.id; }
            }

            public ClaimSet Issuer
            {
                get { return ClaimSet.System; }
            }

            public bool Evaluate(EvaluationContext context, ref object state)
            {
                object obj;
                if (!context.Properties.TryGetValue("Identities", out obj))
                    return false;

                IList<IIdentity> identities = obj as IList<IIdentity>;
                if (obj == null || identities.Count <= 0)
                    return false;

                context.Properties["Principal"] = new CustomPrincipal(identities[0]);
                return true;
            }
        }

        class CustomPrincipal : IPrincipal
        {
            IIdentity identity;
            public CustomPrincipal(IIdentity identity)
            {
                this.identity = identity;
            }

            public IIdentity Identity
            {
                get { return this.identity; }
            }

            public bool IsInRole(string role)
            {
                return true;
            }
        }
    }
}
Namespace CustomMode
	Public Class Test
		Public Shared Sub Main()
			Try
				Dim ppwm As New ShowPrincipalPermissionModeCustom()
				ppwm.Run()

			Catch exc As Exception
				Console.WriteLine("Error: {0}", exc.Message)
				Console.ReadLine()
			End Try
		End Sub
	End Class

	Friend Class ShowPrincipalPermissionModeCustom
		<ServiceContract> _
		Private Interface ISecureService
			<OperationContract> _
			Function Method1(ByVal request As String) As String
		End Interface

		<ServiceBehavior> _
		Private Class SecureService
			Implements ISecureService
            <PrincipalPermission(SecurityAction.Demand, Role:="everyone")> _
            Public Function Method1(ByVal request As String) As String Implements ISecureService.Method1
                Return String.Format("Hello, ""{0}""", Thread.CurrentPrincipal.Identity.Name)
            End Function
		End Class

		Public Sub Run()
			Dim serviceUri As New Uri("http://localhost:8006/Service")
			Dim service As New ServiceHost(GetType(SecureService))
			service.AddServiceEndpoint(GetType(ISecureService), GetBinding(), serviceUri)
			Dim policies As New List(Of IAuthorizationPolicy)()
			policies.Add(New CustomAuthorizationPolicy())
			service.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly()
			service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom
			service.Open()

			Dim sr As New EndpointAddress(serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name))
			Dim cf As New ChannelFactory(Of ISecureService)(GetBinding(), sr)
			Dim client As ISecureService = cf.CreateChannel()
			Console.WriteLine("Client received response from Method1: {0}", client.Method1("hello"))
			CType(client, IChannel).Close()
			Console.ReadLine()
			service.Close()
		End Sub

		Public Shared Function GetBinding() As Binding
			Dim binding As New WSHttpBinding(SecurityMode.Message)
			binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
			Return binding
		End Function

		Private Class CustomAuthorizationPolicy
			Implements IAuthorizationPolicy
			Private id_Renamed As String = Guid.NewGuid().ToString()

			Public ReadOnly Property Id() As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id
				Get
					Return Me.id_Renamed
				End Get
			End Property

			Public ReadOnly Property Issuer() As ClaimSet Implements IAuthorizationPolicy.Issuer
				Get
					Return ClaimSet.System
				End Get
			End Property

			Public Function Evaluate(ByVal context As EvaluationContext, ByRef state As Object) As Boolean Implements IAuthorizationPolicy.Evaluate
                Dim obj As Object = Nothing
				If (Not context.Properties.TryGetValue("Identities", obj)) Then
					Return False
				End If

				Dim identities As IList(Of IIdentity) = TryCast(obj, IList(Of IIdentity))
				If obj Is Nothing OrElse identities.Count <= 0 Then
					Return False
				End If

				context.Properties("Principal") = New CustomPrincipal(identities(0))
				Return True
			End Function
		End Class

		Private Class CustomPrincipal
			Implements IPrincipal
			Private identity_Renamed As IIdentity
			Public Sub New(ByVal identity As IIdentity)
				Me.identity_Renamed = identity
			End Sub

			Public ReadOnly Property Identity() As IIdentity Implements IPrincipal.Identity
				Get
					Return Me.identity_Renamed
				End Get
			End Property

			Public Function IsInRole(ByVal role As String) As Boolean Implements IPrincipal.IsInRole
				Return True
			End Function
		End Class
	End Class
End Namespace

Kompilieren des Codes

Verweise auf die folgenden Namespaces sind zum Kompilieren des Codes erforderlich:

Siehe auch

PrincipalPermissionMode
PrincipalPermissionMode
PrincipalPermissionAttribute
Vorgehensweise: Verwenden des Rollenanbieters für den ASP.NET bei einem Dienst
Vorgehensweise: Einschränken des Zugriffs mit der PrincipalPermissionAttribute-Klasse