WCF(Windows Communication Foundation)의 ID 기능을 사용하면 클라이언트가 서비스의 예상 ID를 미리 지정할 수 있습니다. 서버가 클라이언트에 인증할 때마다 ID가 예상 ID에 대해 검사됩니다. ID 및 작동 방식에 대한 설명은 서비스 ID 및 인증을 참조하세요.
필요한 경우 사용자 지정 ID 검증 도구를 사용하여 확인을 사용자 지정할 수 있습니다. 예를 들어 추가 서비스 ID 확인 검사를 수행할 수 있습니다. 이 예제에서 사용자 지정 ID 검증 도구는 서버에서 반환된 X.509 인증서의 추가 클레임을 확인합니다. 샘플 애플리케이션은 서비스 ID 샘플을 참조하세요.
EndpointIdentity 클래스를 확장하려면
클래스에서 파생되는 새 클래스를 정의합니다 EndpointIdentity . 다음은 확장명 이름을 지정하는 예제입니다
OrgEndpointIdentity
.서비스에서 반환된 보안 토큰의 클레임에 대해 ID 검사를 수행하기 위해 확장 IdentityVerifier 클래스에서 사용할 속성과 함께 프라이빗 멤버를 추가합니다. 이 예제는 하나의 속성인
OrganizationClaim
속성을 정의합니다.public class OrgEndpointIdentity : EndpointIdentity { private string orgClaim; public OrgEndpointIdentity(string orgName) { orgClaim = orgName; } public string OrganizationClaim { get { return orgClaim; } set { orgClaim = value; } } }
Public Class OrgEndpointIdentity Inherits EndpointIdentity Private orgClaim As String Public Sub New(ByVal orgName As String) orgClaim = orgName End Sub Public Property OrganizationClaim() As String Get Return orgClaim End Get Set(ByVal value As String) orgClaim = value End Set End Property End Class
IdentityVerifier 클래스를 확장하려면
에서 IdentityVerifier파생되는 새 클래스를 정의합니다. 다음은 확장명 이름을 지정하는 예제입니다
CustomIdentityVerifier
.public class CustomIdentityVerifier : IdentityVerifier { // Code to be added. public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { throw new Exception("The method or operation is not implemented."); } public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { throw new Exception("The method or operation is not implemented."); } }
Public Class CustomIdentityVerifier Inherits IdentityVerifier ' Code to be added. Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _ ByVal authContext As AuthorizationContext) As Boolean Throw New Exception("The method or operation is not implemented.") End Function Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _ <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean Throw New Exception("The method or operation is not implemented.") End Function End Class
CheckAccess 메서드를 재정의합니다. 이 메서드는 ID 확인의 성공 또는 실패 여부를 결정합니다.
메서드에는
CheckAccess
두 개의 매개 변수가 있습니다. 첫 번째는 클래스의 인스턴스입니다 EndpointIdentity . 두 번째는 클래스의 인스턴스입니다 AuthorizationContext .메서드 구현에서 클래스의 속성에서 반환된 ClaimSets 클레임의 AuthorizationContext 컬렉션을 검사하고 필요에 따라 인증 검사를 수행합니다. 이 예제에서는 "고유 이름" 형식의 클레임을 찾은 다음 이름을 (
OrgEndpointIdentity
)의 EndpointIdentity 확장과 비교합니다.public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { bool returnvalue = false; foreach (ClaimSet claimset in authContext.ClaimSets) { foreach (Claim claim in claimset) { if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname") { X500DistinguishedName name = (X500DistinguishedName)claim.Resource; if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim)) { Console.WriteLine($"Claim Type: {claim.ClaimType}"); Console.WriteLine($"Right: {claim.Right}"); Console.WriteLine($"Resource: {claim.Resource}"); Console.WriteLine(); returnvalue = true; } } } } return returnvalue; }
Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _ ByVal authContext As AuthorizationContext) As Boolean Dim returnvalue = False For Each claimset In authContext.ClaimSets For Each claim In claimset If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then Dim name = CType(claim.Resource, X500DistinguishedName) If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then Console.WriteLine("Claim Type: {0}", claim.ClaimType) Console.WriteLine("Right: {0}", claim.Right) Console.WriteLine("Resource: {0}", claim.Resource) Console.WriteLine() returnvalue = True End If End If Next claim Next claimset Return returnvalue End Function
TryGetIdentity 메서드를 구현하려면
클라이언트에서 TryGetIdentity 클래스의 EndpointIdentity 인스턴스를 반환할 수 있는지 여부를 결정하는 메서드를 구현합니다. WCF 인프라는 먼저 메서드의 구현을
TryGetIdentity
호출하여 메시지에서 서비스의 ID를 검색합니다. 다음으로, 인프라는 반환된EndpointIdentity
과 AuthorizationContext로CheckAccess
구현을 호출합니다.메서드에
TryGetIdentity
다음 코드를 입력합니다.public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity); }
Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _ <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity) End Function
사용자 지정 바인딩을 구현하고 사용자 지정 IdentityVerifier를 설정하려면
Binding 개체를 반환하는 메서드를 만듭니다. 이 예제에서는 클래스의 인스턴스를 WSHttpBinding 만들고 해당 보안 모드를 MessageClientCredentialTypeNone로 설정합니다.
CreateBindingElements 메서드를 사용하여 BindingElementCollection을(를) 만드세요.
컬렉션에서 SecurityBindingElement 반환하고 변수로 SymmetricSecurityBindingElement 캐스팅합니다.
이전에 생성한
CustomIdentityVerifier
클래스의 새 인스턴스를 LocalClientSecuritySettings 클래스의 IdentityVerifier 속성으로 설정합니다.public static Binding CreateCustomSecurityBinding() { WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message); //Clients are anonymous to the service. binding.Security.Message.ClientCredentialType = MessageCredentialType.None; //Secure conversation is turned off for simplification. If secure conversation is turned on, then //you also need to set the IdentityVerifier on the secureconversation bootstrap binding. binding.Security.Message.EstablishSecurityContext = false; // Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier. BindingElementCollection outputBec = binding.CreateBindingElements(); SymmetricSecurityBindingElement ssbe = (SymmetricSecurityBindingElement)outputBec.Find<SecurityBindingElement>(); //Set the Custom IdentityVerifier. ssbe.LocalClientSettings.IdentityVerifier = new CustomIdentityVerifier(); return new CustomBinding(outputBec); }
Public Shared Function CreateCustomSecurityBinding() As Binding Dim binding As New WSHttpBinding(SecurityMode.Message) With binding.Security.Message 'Clients are anonymous to the service. .ClientCredentialType = MessageCredentialType.None 'Secure conversation is turned off for simplification. If secure conversation is turned on, then 'you also need to set the IdentityVerifier on the secureconversation bootstrap binding. .EstablishSecurityContext = False End With ' Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier. Dim outputBec = binding.CreateBindingElements() Dim ssbe = CType(outputBec.Find(Of SecurityBindingElement)(), SymmetricSecurityBindingElement) 'Set the Custom IdentityVerifier. ssbe.LocalClientSettings.IdentityVerifier = New CustomIdentityVerifier() Return New CustomBinding(outputBec) End Function
반환되는 사용자 지정 바인딩은 클라이언트 및 클래스의 인스턴스를 만드는 데 사용됩니다. 그런 다음 클라이언트는 다음 코드와 같이 서비스에 대한 사용자 지정 ID 확인 검사를 수행할 수 있습니다.
using (CalculatorClient client = new CalculatorClient(customSecurityBinding, serviceAddress)) {
Using client As New CalculatorClient(customSecurityBinding, serviceAddress)
예제 1
다음 예제에서는 IdentityVerifier 클래스의 전체 구현을 보여줍니다.
class CustomIdentityVerifier : IdentityVerifier
{
public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
{
bool returnvalue = false;
foreach (ClaimSet claimset in authContext.ClaimSets)
{
foreach (Claim claim in claimset)
{
if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname")
{
X500DistinguishedName name = (X500DistinguishedName)claim.Resource;
if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim))
{
Console.WriteLine($"Claim Type: {claim.ClaimType}");
Console.WriteLine($"Right: {claim.Right}");
Console.WriteLine($"Resource: {claim.Resource}");
Console.WriteLine();
returnvalue = true;
}
}
}
}
return returnvalue;
}
public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
{
return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity);
}
}
Friend Class CustomIdentityVerifier
Inherits IdentityVerifier
Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _
ByVal authContext As AuthorizationContext) As Boolean
Dim returnvalue = False
For Each claimset In authContext.ClaimSets
For Each claim In claimset
If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then
Dim name = CType(claim.Resource, X500DistinguishedName)
If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then
Console.WriteLine("Claim Type: {0}", claim.ClaimType)
Console.WriteLine("Right: {0}", claim.Right)
Console.WriteLine("Resource: {0}", claim.Resource)
Console.WriteLine()
returnvalue = True
End If
End If
Next claim
Next claimset
Return returnvalue
End Function
Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _
<System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity)
End Function
End Class
예제 2
다음 예제에서는 EndpointIdentity 클래스의 전체 구현을 보여줍니다.
public class OrgEndpointIdentity : EndpointIdentity
{
private string orgClaim;
public OrgEndpointIdentity(string orgName)
{
orgClaim = orgName;
}
public string OrganizationClaim
{
get { return orgClaim; }
set { orgClaim = value; }
}
}
Public Class OrgEndpointIdentity
Inherits EndpointIdentity
Private orgClaim As String
Public Sub New(ByVal orgName As String)
orgClaim = orgName
End Sub
Public Property OrganizationClaim() As String
Get
Return orgClaim
End Get
Set(ByVal value As String)
orgClaim = value
End Set
End Property
End Class