Document directory
WSE (Web Services Enhancements) is a function enhancement plug-in launched by Microsoft to enable developers to create more powerful and useful Web Services through. NET. The latest version is WSE2.0 (SP2). This article describes how to use the security feature enhancement section in WSE2.0 to implement secure Web Services. WSE Security features are enhanced by the WS-Security Standard, which is the Security protocol of WebService. It is jointly developed by IBM, BEA, Microsoft, and so on. NET and Java systems.
I mainly write based on the WSE document description and my own experience (in fact, most of them are based on the document). If there are any errors, please point out. In addition, it uses 2.0, which is greatly changed compared with WSE1.0, especially in terms of security.
Another note is that there are two ways to implement security through WSE: one is the method to write code which we will introduce below; the other method is to directly write a policy file (XML document). Both methods are based on the settings of the transmitted SOAP message, such as adding user messages, encryption and decryption, and signature verification, to implement security functions. However, I am not familiar with the second method and have no time to study it.
1. Use the user name and password to verify the Web Services caller identity.
The principle is simple: the client uses SOAP extension to add the user name and password (plaintext or encrypted) to the SOAP message and send it to the Web Services end. After the server receives the message, you can also obtain the username and password from the message context through extension, and then perform authentication and other operations. The following are the implementation steps:
Client:
1. Add Microsoft. Web. Services2 and Web Services references to be accessed by the client. There is nothing to say. Of course, these two references are required. You may need to add other references to the client.
2. Modify the local proxy class generated by referencing Web Services. The code of this class is in the Reference generated Reference file. Open the Web Services Reference folder in Solution Explorer on the right of the. NET development environment, open the Reference. map node, and you will see the Reference. cs or Reference. vb file. If you do not see these files, it may not show all files. You need to set "show all files" in Solution Explorer or command menu "project ". Find the Reference file, open it, and change the inherited parent class of the class to Microsoft in the proxy class declaration. web. services2.WebServicesClientProtocol. only in this way can the proxy class access the SOAP extension provided by WSE. Note: If the Web service reference is updated, You need to modify the inheritance class again.
3. Add the user name and password through the instance of the UsernameToken class. UsernameToken belongs to the Microsoft. Web. Services2.Security. Tokens namespace. Assume that the local proxy class of Web Services is named WebServer. WebService, the user name is Username, and the user password is Userpwd. The code can be as follows (vb.net, the same below ):
'Generate a local proxy instance
Dim mywebserv as New WebServer. WebService
'Generate A UsernameToken instance and write the username, user password, and password sending method in the instance.
Dim untoken As UsernameToken = New UsernameToken (Username, Userpwd, PasswordOption. SendPlainText)
'Set the SOAP message validity period to reduce the possibility of re-use a message even if it is intercepted by another user. Here, it is set to 30 seconds, but pay attention to the clock synchronization problem between different systems.
Mywebserv. RequestSoapContext. Security. Timestamp. TtlInSeconds = 30
'Add the UsernameToken instance to the context of the SOAP message
Mywebserv. RequestSoapContext. Security. Tokens. Add (untoken)
'Webmethod
Mywebserv. WebMethod
Set the password sending method. The sending methods of passwords are enumeration data: SendNone, SendHashed, and SendPlainText. They are not sending passwords, sending password hash values, and sending password plaintext. The above example uses sending plaintext. If SendNone is selected, the server does not verify the password. This security level is very low. If the service needs to sign the passed SOAP message, the client must provide a separate password to sign it; sendHashed refers to sending the SHA-1 hash value of the password. In this case, the password is secure, which is also the best method recommended by Microsoft. However, the server needs to write code and configure the config file to authenticate the user's identity. The specific authentication method is described in the following server settings. SendPlainText is a password transmitted in plaintext, if this method is used, it is best to encrypt the UsernameToken in the above Code, otherwise the password is easily intercepted. The encryption method will be discussed in detail later. In addition, if the server chooses to enable WSE to automatically perform authentication based on the users in the Windows Active Directory domain, you must select send plaintext here.
Server:
1. First, add the WSE configuration element to the Web. config configuration file of Web Services. This is also the most basic step for the system developed by. NET to use WSE. In the WSE document, this configuration is required only when the service caller is an ASP. NET system. If it is a common Client program, this ID is not required. However, I found that this configuration still needs to be added even if the caller is a Client program. The following is a complete configuration document.
<Configuration>
<System. web>
<WebServices>
<SoapExtensionTypes>
<Add type = "Microsoft. web. services2.WebServicesExtension, Microsoft. web. services2, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35 "priority =" 1 "group =" 0 "/>
</SoapExtensionTypes>
</WebServices>
</System. web>
</Configuration>
Of course, in general, you only need. <system. web>... </system. web> Add <webServices>... </webServices>. In addition, it is recommended that the data of the add element be written as one line, otherwise errors may occur.
2. This step is optional when configuring the authentication behavior of the server call.
As mentioned above, the user information has been added to the SOAP message sent by the caller. The server must parse the information, compare and verify the information according to certain rules, and return results.
The preceding processing process also has two options: one is to enable WSE to automatically verify, and our own code and configuration file no longer need to do anything. In this case, after the server receives the SOAP message from the caller, WSE extracts the username and password from the UsernameToken, this is also the reason why the user password must be sent in plain text under the automatic verification mentioned above. After the user name and password are obtained, WSE is used for identification and verification based on the user in the Windows domain where the system is located. That is to say, WSE traverses the user list in the Active Directory to find whether there is a valid user account that matches the received user name/password. If no matched user is found, then, an unauthorized caller error is returned. In this way, the application system and users need to be closely bound with the Windows domain, which lacks flexibility and is not suitable for interfacing with existing business systems. Therefore, the second method should be used in practical applications.
The core of this method is that Web Services is implemented by inheriting the UsernameTokenManager class and reloading the AuthenticateToken method.
A. first declare a class inherited from UsernameTokenManager.
Public Class CustomUsernameTokenManager
Inherits UsernameTokenManager
There is an access permission issue here. To enable authorized assembly to access this class, you also need to add some access restrictions when declaring it. Because the trust level of the Assembly that can access the UnmanagedCode is relatively high, it is required that the Assembly that can access this class can access the UnmanagedCode. In this way, the above statement becomes the following form:
<SecurityPermission (SecurityAction. Demand, Flags: = SecurityPermissionFlag. UnmanagedCode)> Public Class CustomUsernameTokenManager
Inherits UsernameTokenManager
Of course, you can configure Other permission requirements as long as you change the SecurityPermissionFlag enumeration value of Flags.
B. Reload the AuthenticateToken method in the code. After the server receives a SOAP message containing the UsernameToken instance, WSE deserializes the UsernameToken and calls the VerifyToken method. The VerifyToken method calls the AuthenticateToken method during execution, this method returns a password value, and WSE compares it with the password in UsernameToken. If the password sent is plain text (UsernameToken. passwordOption = SendPlainText), it is compared directly; if the sending password is a hash value (UsernameToken. passwordOption = SendHashed), then WSE will perform a SHA-1 hash operation on the returned value, and then compare the result with the password in UsernameToken. If they are inconsistent, an unauthorized user error is returned. The above process is completed automatically. Therefore, we need to reload the AuthenticateToken method to return the correct user password for comparison and verification. This is actually equivalent to PasswordProvider in WSE1.0.
The logic for implementing the method of reload AuthenticateToken is determined by the system according to specific requirements. For example, you can find the corresponding user password in the database based on the user name or in LDAP. As shown in the WSE document, the returned password is the same as the submitted username.
Protected Overrides Function AuthenticateToken (ByVal userName As UsernameToken) As String
'Enable' that the SOAP message sender passed a UsernameToken.
If userName Is Nothing Then
Throw New ArgumentNullException
End If
'This is a very simple provider.
'In most production systems the following code
'Typically consults an external database of (userName, hash)
'Pairs. For this example, it is the UTF-8
'Encodingof the user name.
Dim encodedUsername As Byte () = _
System. Text. Encoding. UTF8.GetBytes (userName. Username)
Return System. Text. Encoding. UTF8.GetString (encodedUsername)
End Function
C. Configure the web. config file to inform Web Services of the class used to authenticate the user's identity.
First, add the element indicating the use of WSE2 to the file:
<Configuration>
<ConfigSections>
<Section name = "microsoft. web. services2"
Type = "Microsoft. Web. Services2.Configuration. WebServicesConfiguration, Microsoft. Web. Services2, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"/>
</ConfigSections>
</Configuration>
Note that <configSections>... </configSections> write the entire <configuration>... </configuration>. Otherwise, the error "text/html; charset = UTF-8" is returned, but it should be "text/xml.
Configure the UsernameTokenManager subclass.
<Configuration>
<Microsoft. web. services2>
<Security>
<SecurityTokenManager xmlns: wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" qname = "wsse: UsernameToken" type = "MyNamespace. example, MyAssemblyName, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = example"/>
</Security>
</Microsoft. web. services2>
</Configuration>
Here, the value of the type attribute must be kept in one row. "MyNamespace. CustomUsernameTokenProvider" must be a valid class level name for the derived class, and "MyAssemblyName" must be the Assembly name. In addition, attributes such as Version, Culture, and PublicKeyToken can be omitted.
In this way, we have completed the most basic user name/password-based authentication for Web Service calls. In the future, security functions will be implemented based on it.
Ii. Sign a SOAP message using the user name and password
The above process implements Web Services user identity confirmation. However, it cannot ensure that the SOAP message received by Web Services is sent by the declared user. Therefore, in actual applications, the caller must sign the SOAP message, the signature is sent together with the message. After receiving the message, the server also needs to authenticate the signature. To confirm that the message has not been changed during transmission, and the verified user is the user who signed the message.
Client:
You only need to add a signature to the SOAP message of the original client, as shown in the following figure. The new Code is added to the blacklist:
Mywebserv. RequestSoapContext. Security. Tokens. Add (untoken)
Mywebserv. RequestSoapContext. Security. Elements. Add (New _
MessageSignature (untoken ))
Mywebserv. WebMethod
The above code is that the client generates a signature based on the UsernameToken instance, and then adds the signature to the SOAP message, specifically the WS-Security extended SOAP message header.
Server:
In fact, the server does not need to be changed. As long as the SOAP message sent by the client contains a signature, the server automatically verifies the validity of the signature. The server first verifies the user name/password, and then uses the user name passed by the client and the password obtained by itself (WSE is automatically obtained from the Windows Active Directory, or through the overloaded AuthenticateToken method) verify the signature. If the verification fails, the message is changed during transmission or is not signed by the currently called user, and an error is returned.
This section of the WSE help document adds a function to determine whether or not SOAP contains a signature. It is not necessary to obtain the signature information. If you are interested, you can check it yourself.
3. Use a certificate to authenticate the identity and sign the SOAP message
User Names/passwords have inherent drawbacks. Therefore, in some systems with strict security requirements, we also need to use certificates to authenticate user identities. The basic knowledge about PKI/CA is not introduced here. You can refer to the relevant materials.
First, we need to configure the server to ensure that WSE can access the certificate and its private key. (As for certificate application, management and use are basic knowledge, so I won't talk about it here.) Here, we mainly set it on the Web Services side to ensure that the server can automatically complete certain functions, user intervention is not required. In the Web. config file, add the following <x509> element (in the black body ):
<Configuration>
<Microsoft. web. services2>
<Security>
<X509 storeLocation = "CurrentUser"/>
</Security>
</Microsoft. web. services2>
</Configuration>
The storeLocation attribute is the certificate storage that WSE can access. The optional values include "LocalMachine" and "CurrentUser", indicating the local certificate storage and the current user certificate storage respectively. CurrentUser is used here, while storeLocation defaults to LocalMachine. the other attributes are configured as follows: verifyTrust: whether to verify the validity of the certificate chain used. The default value is true; allowTestRoot: whether the certificate issued by the test Root CA is considered valid during the certificate chain process, this parameter is valid only when verifyTrust is true. The default value is false. allowRevocationUrlRetrieval indicates whether the certificate is revoked online. It is valid only when verifyTrust is true. The default value is true. allowUrlRetrieval, whether to verify the certificate chain validity online, allowRevocationUrlRetrieval, and whether to verify the certificate revocation status online.
Client:
Steps 1st and 2 are basically the same as steps for using the user name/password in section 1. But here we also need to add a reference: Microsoft. Web. Services2.Security. X509
3. Write the code to obtain the certificate to be used. I used a listview control to display the personal certificate in the current user certificate store for the user to choose. You can also use the certificate attributes as in the WSE document to locate the required certificate. The name of the Listview control is lv_certlist, which has two columns: the name of the certificate holder and the issuer.
Dim cert As X509Certificate
Dim lvitem As ListViewItem
'Open the personal certificate library from the current user certificate store
Certstore = X509CertificateStore. CurrentUserStore (X509CertificateStore. MyStore)
Certstore. Open ()
Lv_certlist.Items.Clear ()
'Print the certificate and write it to the listview control.
For Each cert In certstore. Certificates
Lvitem = lv_certlist.Items.Add (cert. GetName)
Lvitem. SubItems. Add (cert. GetIssuerName)
Lvitem. Tag = lvitem. Index
Next cert
4. Select the selected certificate to generate the X509SecurityToken instance, which is a subclass of SecurityToken like the previous UsernameToken.
Dim cert As X509Certificate
Dim certToken As X509SecurityToken
Dim result As String
Cert = certstore. Certificates (lv_certlist.SelectedIndices (0 ))
'Determine whether the selected Certificate supports signature and whether the private key exists
If cert. SupportsDigitalSignature And Not (cert. Key Is Nothing) Then
'Print the certificate and write it to the listview control.
CertToken = New X509SecurityToken (cert)
Dim mywebserv As New WebServer. WebService
Mywebserv. RequestSoapContext. Security. Timestamp. TtlInSeconds = 30
'Add the X509SecurityToken containing the Certificate Information
Mywebserv. RequestSoapContext. Security. Tokens. Add (certToken)
'Sign the SOAP message using the certificate and write the result in the message
Mywebserv. RequestSoapContext. Security. Elements. Add (New _
MessageSignature (certToken ))
'Method of calling the Web Service
Mywebserv. WebMethod
End If
Server:
Similar to the message used to sign the user name/password, the server automatically verifies the validity of the signature. In addition, the server verifies the certificate validity Based on the attribute settings in the <x509> element in the web. config file. If verification fails, an error is returned. The certificate used for signature can be obtained through SoapContext. Security. Tokens
4. Use the user name and password to encrypt the SOAP message
As mentioned in section 1 above, if the password in the UsernameToken instance is in plain text, it is best to encrypt and send the UsernameToken. Make the following changes in the client code in section 1, and add the boldlike code:
Mywebserv. RequestSoapContext. Security. Tokens. Add (untoken)
Mywebserv. RequestSoapContext. Security. Elements. Add (New _
Microsoft. Web. Services2.Security. EncryptedData (untoken ))
Mywebserv. WebMethod
The above code is that the client encrypts the SOAP message according to the UsernameToken, and then adds the ciphertext to the soap message, specifically the WS-Security extended SOAP message header.
The server automatically decrypts the message. The server first verifies the user name/password, and then decrypts the data using the user name passed by the client and the obtained password (WSE is automatically obtained from the Windows Active Directory, or through the overloaded AuthenticateToken method. If it fails, an error is returned.
The WSE help document also adds a function to determine whether SOAP is encrypted.
5. Use Certificates to encrypt and decrypt SOAP messages
This is slightly more complex. According to the principle of PKI asymmetric encryption and decryption, the client that encrypts the message needs to obtain the certificate public key of the server that serves as the receiver in advance, and the server must ensure that the private key corresponding to the certificate can be accessed. Therefore, we must first set the certificate used by the server. The principle is to enable the server to automatically access the private key corresponding to the certificate at any time.
For Web Services developed based on ASP. NET, the default user must be granted the permission to access the private key of the certificate. The Default User of Web Services running on IIS 6.0 is Network Service. In other cases, the user account is owned by machine. the userName attribute of the <processModel> element in the config file is determined. The default value is "machine", which is equivalent to the ASPNET account. To add a Certificate, run the X.509 Certificate tool (--- program --- Microsoft WSE 2.0 --- X.509 Certificate tool) that comes with WSE 2.0, and select and open the Certificate to be accessed by WSE. After the certificate is opened, the Private Key File Name is displayed in the "Private Key File Name" text box, and the Private Key File path is displayed in the "Private Key File Name" text box. Click "Private Key File Properties" to open the File Properties dialog box. You can add the authorized Network Service or ASPNET user account to the security Properties page.
If the private key file does not exist or is inaccessible after the certificate is opened, the certificate is faulty or the private key is protected, for example, password-protected or stored in security peripherals, it cannot be automatically accessed by Web Services at any time, so it is not applicable.
For Web Services, if you are using the default ASPNET, you 'd better select the certificate in the Local Machine Store. Because the ASPNET user is automatically generated when ASP. NET is installed, its password cannot be accessed. If the certificate is included in the current user Store, the server may not be able to access the private key.
After the server sets the certificate, the client will obtain the certificate and public key. The specific method has something to do with your business system and application requirements. You can place it on the webpage for users to download and install it in advance. If the application is in a LAN environment, the client can be obtained in LDAP or CA.
The client makes the following changes:
Mywebserv. RequestSoapContext. Security. Tokens. Add (certToken)
'Add encryption results to a SOAP message
Mywebserv. RequestSoapContext. Security. Elements. Add (New _
Microsoft. Web. Services2.Security. EncryptedData (certToken ))
Mywebserv. WebMethod
After the server receives the encrypted SOAP message, it automatically decrypts it using the corresponding private key. If it fails, an error is returned.
It can be seen that the difficulty in using certificates to encrypt and decrypt messages lies in the selection and configuration of certificates, especially the message receiving end.
In addition to the above username/password, WSE supports two tokens: X509 Certificate. It also supports Kerberos Ticket, Security Context Token, and user-defined Token. Kerberos Ticket is like the content added by WSE. It is not included in the standard WS-Security, and is only supported on Windows XP SP1/SP2 and Windows2003. The security context token must be generated by a context token service. The core of a user-defined token is that SecurityToken derives a user's own licensing class to complete various security functions. In short, WSE uses this token-based and extended SOAP message to implement Web Services security.