Udostępnij za pośrednictwem


How to: Authorize the Message Sender Based on a User Name and Password

WSE enables you to authorize access to a Web service method based on a UsernameToken used to sign the SOAP message. When a SOAP message is received and the UsernameToken authentication is enabled, WSE attempts to authenticate the SOAP message sender. Authentication is done by WSE by calling the Win32 API LsaLogonUser with the user name and password contained within the UsernameToken that signed the SOAP message. If that succeeds, the Principal property of the UsernameToken is assigned a principal representing the authenticated user.

For an overview of authorization support in WSE, see Authorizing Access to a Web Service.

The following procedures detail how to use code to authorize access to a Web service by using a user name and password. Whether you use policy or code, WSE must be enabled to process the incoming SOAP messages.

To use code to authorize access to a Web service method

  1. Configure the Web service to authenticate received UsernameToken security tokens.

    For more information, see How to: Verify Digital Signatures of SOAP Messages Signed Using a User Name and Password.

  2. Add code to the Web service method that obtains the UsernameToken that the application wants to use for authentication and authorization.

    A SOAP message can contain multiple security tokens, which might sign or encrypt different portions of the SOAP message. Therefore, it is up to the application to decide which security token is used for authentication and authorization. The following code example defines and then calls a GetBodySigningToken method that obtains the UsernameToken that signed the <Body> element of the SOAP request.

    Public Function GetBodySigningToken(ByVal requestContext As SoapContext) As UsernameToken
        Dim token As UsernameToken = Nothing
        Dim securityElement As ISecurityElement
        For Each securityElement In _
            requestContext.Security.Elements
            If (TypeOf securityElement Is MessageSignature) Then
                Dim sig As MessageSignature = _
                    CType(securityElement, MessageSignature)
                If ((sig.SignatureOptions And _
                    SignatureOptions.IncludeSoapBody) <> 0) Then
                    Dim sigToken As SecurityToken = sig.SigningToken
                    If (TypeOf sigToken Is UsernameToken) Then
                        token = CType(sigToken, UsernameToken)
                    End If
                End If
            End If
        Next
        Return token
    End Function
    
    public UsernameToken GetBodySigningToken(SoapContext 
        requestContext)
    {
        UsernameToken token = null;
        foreach (ISecurityElement securityElement in
            requestContext.Security.Elements)
        {
            if (securityElement is MessageSignature)
            {
                MessageSignature sig =
                    (MessageSignature)securityElement;
                if ((sig.SignatureOptions &
                    SignatureOptions.IncludeSoapBody) != 0)
                {
                    SecurityToken sigToken = sig.SigningToken;
                    if (sigToken is UsernameToken)
                        token = (UsernameToken)sigToken;
                }
            }
        }
        return token;
    }
    

    Add this code to the code in the Web service method.

    ' Ensure that the request is a SOAP request.
    Dim requestContext As SoapContext = RequestSoapContext.Current
    If (requestContext Is Nothing) Then
        Throw New ApplicationException("Only SOAP requests are permitted.")
    End If
    
    ' Get the UsernameToken security token that was used to sign the SOAP
    ' request.
    Dim token As UsernameToken = GetBodySigningToken(requestContext)
    
    // Ensure that the request is a SOAP request.
    SoapContext requestContext = RequestSoapContext.Current;
    if (requestContext == null)
        throw new ApplicationException("Only SOAP requests are permitted.");
    
    // Get the UsernameToken security token that was used to sign the SOAP
    // request.
    UsernameToken token = GetBodySigningToken(requestContext);
    
  3. Ensure that the user is a member of the role or roles authorized to call this Web service method.

    The following example code ensures that a UsernameToken was used to sign the SOAP message and that the user is a member of the Tellers role.

    If (token Is Nothing OrElse Not token.Principal.IsInRole("Tellers")) Then
        Throw New UnauthorizedAccessException
    End If
    
    if (token == null || !token.Principal.IsInRole("Tellers"))
        throw new UnauthorizedAccessException();
    

Example

The following code example authorizes SOAP requests to the SayHello Web service in which a UsernameToken security token signs the SOAP <Body> element and the user is a member of the Tellers role.

Imports System
Imports System.Web.Services

Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Tokens

Namespace WSESamples
    <WebService(Namespace:="https://www.contoso.com/Service1")> _
    Public Class Service1
        <WebMethod()> _
        Public Function SayHello() As String
            ' Ensure that the request is a SOAP request.
            Dim requestContext As SoapContext = RequestSoapContext.Current
            If (requestContext Is Nothing) Then
                Throw New ApplicationException("Only SOAP requests are permitted.")
            End If

            ' Get the UsernameToken security token that was used to sign the SOAP
            ' request.
            Dim token As UsernameToken = GetBodySigningToken(requestContext)
            
            If (token Is Nothing OrElse Not token.Principal.IsInRole("Tellers")) Then
                Throw New UnauthorizedAccessException
            End If

            Return "Hello World"
        End Function

        Public Function GetBodySigningToken(ByVal requestContext As SoapContext) As UsernameToken
            Dim token As UsernameToken = Nothing
            Dim securityElement As ISecurityElement
            For Each securityElement In _
                requestContext.Security.Elements
                If (TypeOf securityElement Is MessageSignature) Then
                    Dim sig As MessageSignature = _
                        CType(securityElement, MessageSignature)
                    If ((sig.SignatureOptions And _
                        SignatureOptions.IncludeSoapBody) <> 0) Then
                        Dim sigToken As SecurityToken = sig.SigningToken
                        If (TypeOf sigToken Is UsernameToken) Then
                            token = CType(sigToken, UsernameToken)
                        End If
                    End If
                End If
            Next
            Return token
        End Function
    End Class
End Namespace
using System;
using System.Web.Services;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;

namespace WSESamples
{
    [WebService(Namespace="https://www.contoso.com/Service1")]
    public class Service1
    {
        [WebMethod]
        public string SayHello()
        {
            // Ensure that the request is a SOAP request.
            SoapContext requestContext = RequestSoapContext.Current;
            if (requestContext == null)
                throw new ApplicationException("Only SOAP requests are permitted.");
            
            // Get the UsernameToken security token that was used to sign the SOAP
            // request.
            UsernameToken token = GetBodySigningToken(requestContext);
            
            if (token == null || !token.Principal.IsInRole("Tellers"))
                throw new UnauthorizedAccessException();
            return "Hello World";
        }

        public UsernameToken GetBodySigningToken(SoapContext 
            requestContext)
        {
            UsernameToken token = null;
            foreach (ISecurityElement securityElement in
                requestContext.Security.Elements)
            {
                if (securityElement is MessageSignature)
                {
                    MessageSignature sig =
                        (MessageSignature)securityElement;
                    if ((sig.SignatureOptions &
                        SignatureOptions.IncludeSoapBody) != 0)
                    {
                        SecurityToken sigToken = sig.SigningToken;
                        if (sigToken is UsernameToken)
                            token = (UsernameToken)sigToken;
                    }
                }
            }
            return token;
        }
    }
}

See Also

Tasks

How to: Digitally Sign a SOAP Message
How to: Verify Digital Signatures of SOAP Messages Signed Using a User Name and Password

Reference

UsernameToken

Concepts

Authorizing Access to a Web Service

Other Resources

Signing Custom SOAP Headers