Services|web| programming
Click the download source code to download the source code for the rock Paper Scissors application from Microsoft Download Center.
Directory
- Rock Paper Scissors: A secure, Distributed message processing sample application
- Kerberos token support integrated with Windows security
- Security Policy
- WSE 2.0 Addressing
- TCP Message Processing
- Other features of WSE 2.0
- Summary
Microsoft has published Web Services Enhancements (WSE) version 1.0 to enable security, routing, and attachments in supported products, and it also supports advanced WEB services. Web Services Enhancements 2.0 has evolved from simple support for basic protocols to support the integration of core functionality and operating systems, as well as enhanced policy, trust, and contextual token capabilities.
WSE is also an extension of the. NET Framework support for creating and using WEB services, while WSE 2.0 employs new programming patterns. In the past, Web service support has relied on Internet Information Server (IIS) as its HTTP server host; The WSE 2.0 now supports sending messages over TCP/IP or in-process. In this way, you can send messages from the server to the client through Peer-to-peer, one-way, asynchronous, and so on.
Below, we will briefly describe some of the main features of WSE 2.0 and assume that you are familiar with WSE 1.0. For more information about WSE 1.0, see Programming with WEB Services Enhancements 1.0 for Microsoft. NET (English).
Rock Paper Scissors: A secure, Distributed message processing sample application
To showcase all aspects of WSE 2.0, I want to create an application to showcase some of the new security features and message processing capabilities. Specifically, I prefer to use TCP message processing support to display peer-to-peer communication and make it work in the area of Windows security. I'm thinking of a simple distributed version of the old rock Paper Scissors game that can now be safely distributed with WSE 2.0.
Rock Paper Scissors is a two-person children's game, traditionally including having each child clap three times and presenting the shape of a stone, scissors, or cloth at the third clap. The winner is determined according to the reasons shown in the table below:
Stone cloth scissors stone draw cloth wrap stone.
The Cloth side wins! The stone broke the scissors.
Stone Side Win! Bubu wrapped in stone.
The Cloth side wins! Draw scissors to cut open cloth.
Scissors Square Win! Scissors are broken by stone.
Stone Side Win! Scissors cut and open the cloth.
Scissors Square Win! Draw
The game is usually used to determine who first chooses to play in the sand baseball game, who eats the last ice cream, and even who blows each other's arms.
We move Rock Paper Scissors out of the sand and apply it directly to the security, collaboration, and unity of corporate technology with WSE 2.0. The message processing structure of the game is shown in Figure 1 below.
Figure 1:rock Paper Scissors Message processing and security model
The Rock Paper Scissors has two main components: one is a asp.net Web service named RPSService, and the other is a Peer-to-peer application run by multiple users. RPSService's role is to let users register to play games or find opponents to play the game. The peer application communicates with RPSService first to find the other person to communicate with, and then directly to the other side after the opponent is identified.
Peer-to-peer: For message processing, WSE 2.0 is converted from a traditional HTTP request/response (that is, an RPC environment) to an environment that may have peer messaging, asynchronous message processing, and Message Queuing at the same time.
Kerberos: The entire application was created by using integrated Windows Kerberos support. With WSE 2.0, you can connect to the network in a secure way. We will authenticate, digitally sign, and encrypt messages to ensure the highest security, and this will be entirely based on the Windows user account.
Easy management: Without writing code to control access, we can configure the security of the message through the policy configuration file. Through the policy file, you can control the type of security to be implemented, which part of the message should be digitally signed or encrypted, and how to implement it, and the acceptance conditions can be controlled based on the message time limit. Currently, the appropriate person who can control security is: your administrator.
Rock Paper Scissors: The important role of this application is not in the application itself, but in the way it uses security messages, policies, and addressing when communicating with different entities in this example. You can't guess, I was imagining my boss saying, "To determine the staff bonus this year, I want you each to run a small application RockPaperScissors.exe ..."
Kerberos token support integrated with Windows security
The first part of WSE 2.0 that we want to discuss is to support Kerberos security tokens. WSE 1.0 supports user name tokens and X.509 security tokens. You can add these tokens to a message collection for a security token, and to create a digital signature or to perform encryption. For WSE 2.0来, Kerberos token support has been added when you run on Windows Server 2003 or Windows XP with Service Pack 1. More importantly, Kerberos token support can be used in conjunction with Integrated Windows security, so that you can control access to Web services based on Windows users no longer needing to map user names to Windows users, or to set up user databases separately.
The first thing I do before I add code to RPSService is to add a reference to the Microsoft.Web.Services library in my project. If you have WSE 1.0 installed on your computer, it is important to note that the 2.0 version of the program library is selected when adding references. Fortunately, the assembly's version number is listed after the assembly name, so you can easily select the correct assembly. Figure 2 shows the Add Reference (Add Reference) dialog box with the WSE 2.0 library selected. Note that the 1.0 version of the library is just before the selected library.
Figure 2: Adding a reference to the WSE 2.0 assembly
The following code shows how to programmatically add a Kerberos token to a collection of token messages. It is the code used by a party to send its actions privately to the other party. The code uses the asynchronous TCP message feature of WSE 2.0 (which is described later), but the code used to add tokens and encryption is similar to the code used in WSE 1.0 for other types of tokens.
Using Microsoft.Web.Services.Security.Kerberos; a€| KerberosToken Peertoken; A€|peertoken = new KerberosToken ("host/" + opponenturi.host); A€|envelope. CONTEXT.SECURITY.TOKENS.ADD (peertoken); envelope. CONTEXT.SECURITY.ELEMENTS.ADD (New EncryptedData (Peertoken));
Note that tokens are created by passing the name of the connection host. The Kerberos label used to create this token allows the current user to communicate with the indicated host. Specifically, the token will be used to encrypt the message to be sent so that only the remote host can read the messages.
Unlike other type tokens, the Kerberos token creates the token using the current Windows user security context. If you query a token that you have created, you will find a Principal member property that indicates the user who created the token. We get the user name from the body of the code that receives the message (with the Kerberos token). The following opponent variable is a KerberosToken object that is obtained from the Tokens collection of incoming messages. You can get information about the token creator as you get the name below, but you can also call the IsInRole () method to programmatically determine Active Directory group members.
This.opposingNameLabel.Text = "Playing:" + opponent. Principal.Identity.Name;
Note: If you are running a Web service on Windows XP, you may experience the following error when you try to connect to a Web service using the Kerberos token:
Microsoft.Web.Services.Security.SecurityFault:An Invalid security token is provided---> System.Security.SecurityException:Unable to validate incoming Kerberos ST. LsaLogonUser failed with the following message:a required the ' not ' privilege by the client. Substatus is 0.
This error occurs because the ASPNET account was unable to authenticate the Kerberos token because the security API named LogonUser was invoked. The user account that invokes the LogonUser API requires the "operate as part of the operating system" privilege. By default, the ASPNET account (that is, the account that runs the ASP.net code) does not have this privilege. It is recommended that you run a WEB service that has Kerberos security set up on the appropriate server platform, such as Windows Server 2003. On Windows Server 2003, you do not need to "operate as part of the operating system" privilege when calling LogonUser. On Windows XP, you can use the Local security Policy management application to configure an account that has the "operate as part of the operating system" privilege, including the ASPNET account, but it should be noted that this can cause asp.net applications to be less secure.
Security Policy
Although the code discussed above is very similar to the code in WSE 1.0, it has the advantage of associating a Principal object with a token that can be used to find specific attributes of a specific security token. The problem with this approach is that you still have to write code to determine the access features that should be part of the administrative task. For this reason, WSE 2.0 provides support for creating policy files.
The policy file is based on the Ws-policy specification, which is created to allow WEB services to declare incoming messages about security, and so on. If you want to sign or encrypt all or part of the message, WSE 2.0 allows us to control the security token class used by users of the WEB service in the message, as well as to control restrictions on the time limit for receiving messages, or even to specify role membership restrictions for incoming messages.
The following policy file indicates that a message received by a WEB service should sign the message body using the Kerberos token.
<?xml version= "1.0" encoding= "Utf-8" ><policydocument xmlns= "http://schemas.microsoft.com/wse/2003/06/" Policy "> <mappings xmlns:wse=" Http://schemas.microsoft.com/wse/2003/06/Policy "> <mapdefault policy= "#policy -5903e02b-9c11-4dc5-8ca0-42d4e9d0bcde"/> </mappings> <policies xmlns:wsu= "Http://schem As.xmlsoap.org/ws/2002/07/utility "> <wsp:policy wsu:id=" POLICY-5903E02B-9C11-4DC5-8CA0-42D4E9D0BCDE " xmlns:wsp= "Http://schemas.xmlsoap.org/ws/2002/12/policy" > <wsse:integrity wsp:usage= "wsp:required" xmlns:wsse= "Http://schemas.xmlsoap.org/ws/2002/12/secext" > <wsse:TokenInfo> <securitytoken xmlns= "Http://schemas.xmlsoap.org/ws/2002/12/secext" ><wsse:tokentype>wsse:kerberosv5st</wsse: tokentype> </SecurityToken> </wsse:TokenInfo> <wsse:messageparts dialect= "http:// Schemas.xmlsoap.org/2002/12/wsse#part "> Wsp:body () </wsse:MessageParts> </wsse:Integrity> </wsp:Policy> </policies>< ;/policydocument>
The policydocument root element has two child elements: mappings and policies. The policies element contains one or more Policy elements that represent a specific set of requirements. In the example, the policy contains a Integrity requirement that indicates that the message requires a digital signature. The Tokeninfo element contains information about the type of token that is required, in this example, the Kerberos token. Finally, this particular integrity requires that the part of the document that must be signed is body text, as indicated by using the messageparts element.
The mappings portion of Policydocument Associates only specific endpoints with the policies in the Policies section. This example does not include any mappings for a particular endpoint, only a single default mapping.
In addition to actually creating a policy file, you need to let the WSE library know that the policy exists. Therefore, it is necessary to configure the Web service to use the created policy file. To do this, you need to modify the Web.config file. The following Web.config file gives changes to enable WSE SoapExtension, enable handlers in the WSE configuration section, and add receive policy caching.
<?xml version= "1.0" encoding= "Utf-8"?><configuration> <configSections> <!--Add a reference to the configuration section. Note that the type name wraps to make it easier to read, and should not contain line breaks. --> <section name= "microsoft.web.services" type= "Microsoft.Web.Services.Configuration". Webservicesconfiguration, Microsoft.Web.Services, version=2.0.0.0, Culture=neutral, publickeytoken=31bf385 6ad364e35 "/> </configSections> <system.web><!--for simplicity, delete other elements--> <webServices> <so apextensiontypes> <!--add WSE soapextension. Note that the type name wraps to make it easier to read and should not contain line breaks. --> <add type= "Microsoft.Web.Services.WebServicesExtension, Microsoft.Web.Services, version=2.0.0.0, culture= Neutral,publickeytoken=31bf3856ad364e35 "priority=" 1 "group=" 0 "/> </soapExtensionTypes> </webservices > </system.web> <!--WSE Configuration section--> <microsoft.web.services> <policy> <receive> <cache NAMe= "Policycache.xml"/> </receive> </policy> </microsoft.web.services></configuration>
At this point, the WEB service has been configured to accept only requests that meet the policy requirements in the Policycache.xml file.
If you need to have administrators configure policies for specific Web services, we also want similar configurations for applications that use Web services. All in all, if the administrator changes the policy and we have to regenerate the used application, it does not fully implement the ability to configure the message requirements without rebuilding the WEB service.
To add this feature to the application you are using to send a message that matches a specific policy, you need a local policy file that the program can use. For the rock Paper Scissors Peer-to-peer application that will invoke the. asmx Web Service, we simply copy the Policycache.xml file to the working directory of the executable program. As with a WEB service, configure the application to use the policy file in its. config file (RockPaperScissors.exe.config in this example). The configuration file is shown below.
<?xml version= "1.0" encoding= "Utf-8"?><configuration> <configSections> <!-- Adds a reference to the configuration section. Note that the type name wraps to make it easier to read, and should not contain line breaks. --> <section name= "microsoft.web.services" type= " Microsoft.Web.Services" . Configuration.webservicesconfiguration, Microsoft.Web.Services, version=2.0.0.0, culture=neutral, Publickeytoken=31bf3856ad364e35 "/> </configSections> <microsoft.web.services> <policy> <send> <cache name= "Policycache.xml"/> </send> </policy > </microsoft.web.services></configuration>
The peer application communicates with the WEB service by sending a message that conforms to the requirements in the Policycache.xml file.
WSE 2.0 Addressing
One of the differences between WSE 1.0 and WSE 2.0 is support for ws-addressing. Ws-addressing replaces most of the features of the Ws-routing specification supported in WSE 1.0. Functionally, instead of focusing on the routing path, ws-addressing provides a mechanism to add the to and from headers to the SOAP envelope. Ws-addressing also supports Action, ReplyTo, and FaultTo headers. The Action header is similar to the SOAPAction HTTP header that is typically used when sending SOAP messages over HTTP. For the. asmx Web service, the HTTP SOAPAction header is used to determine which Web method of the service should be invoked when an incoming message is received. Similarly, the Action SOAP header is used to determine which function to call when receiving a message over a non-HTTP transport.
In the Rock Paper Scissors application, we will also use the ReplyTo header to determine the address to receive the next message. When one of the peer applications sends a one-way RegisterPlayer message to RPSService, a ReplyTo endpoint is specified indicating the address at which the peer communication begins to receive the message sent by the other. Similarly, when a second peer application sends a Findplayer message to RPSServer, RPSServer returns a message with a ReplyTo header that indicates the endpoint of the first peer application. This tells the second peer application to send its next message to the endpoint of the first peer application. In the remaining peer messages, continue to specify the ReplyTo header to continuously indicate the address to receive the next message.
The following is part of the code used by the Peer-to-peer application, in which the peer traffic is first listened to, and then the URI is indicated by the ReplyTo header before the RPSServer RegisterPlayer Web method is invoked.
myPeerUri = new Uri ("soap.tcp://" + System.Net.Dns.GetHostName () + ": 3131/rpspeer1"); SoapReceivers.Add (myPeerUri, typeof (PeerService)); Rpsserv.rpsserverwse proxy = new Rpsserv.rpsserverwse ();p Roxy. Requestsoapcontext.replyto = myPeerUri;
TCP Message Processing
In WSE 2.0, message handling is a major part of the new functionality. WSE 2.0 provides support for communication in the process through asynchronous TCP or request/Response mode TCP. In the Rock Paper Scissors application of this example, we will send a message indicating whether the player has selected a stone, cloth, or scissors for a particular game instance. Since we rely on user interaction to determine the content of a message to be sent, we cannot wait indefinitely for a request to send a response, so we use asynchronous TCP messages to implement the communication for a particular game. A person sends its action after the application waits patiently until the other player sends its action. You can view this as similar to sending an invoice to a warehouse, and you must wait until someone manually wraps the material to send a response indicating that the request completed.
In the ReplyTo code shown above, part of the code needed to establish a TCP endpoint is given. You can register the listening code by using the Add method in the SoapReceiver class. In this example, we created a class called PeerService, which is a subclass of the SoapReceiver class that listens for the incoming rock Paper Scissors game. The PeerService class simply overloads the Receive method that handles incoming messages. The code for the class looks like this:
public class peerservice:soapreceiver{The public static Form1 Form; protected override void Receive (SoapEnvelope envelope) { form.opponentplay = (char) envelope. Getbodyobject (typeof (Char)); foreach (SecurityToken tok in envelope. Context.Security.Tokens) {if (Tok is KerberosToken) { form.opponent = (KerberosToken) tok; break;} } Form.opponenturi = envelope. Context.replyto; if (Form.peertoken = = null) Form.peertoken = new KerberosToken ("host/" + Form.OpponentUri.Host); Form.opposingNameLabel.Invoke (New Form1.receiveplaydelegate (Form.receiveplay)); }
The Receive method takes a SoapEnvelope object as an argument. The SoapEnvelope class derives from the XmlDocument class, so that you can access the SOAP body and headers through a standard XML DOM interface. Instead of using the DOM interface, we use the Getbodyobject method to create a class based on XML in the body of the SOAP message, which uses XmlSerializer for functionality. We save the action information in a public property of the Form class.
We also get the Kerberos token from the request and save it. It will be used to get the name of the opponent later. Then, save the ReplyTo URI of the opponent so that we know the address to receive the response. We can also establish a Kerberos token based on the host shown in the URI, which will be used to encrypt the returned message.
SoapReceivers support will listen for incoming connections and call the Receive method of the indicated class when a message is received. A thread in the process's thread pool calls the Receive method, which in most cases is not the thread that handles the application's main window message pump. Therefore, at the end of the Receive method, I invoke the Invoke method through a control in a Windows form. This initiates the delegate functionality specified in the main window thread so that the general interaction of the various controls in the form is correct. In this example, the delegate determines the winner after a two-time action and updates the user interface accordingly.
When the SoapReceivers.Add method is invoked (the method is shown again below), we pass two arguments: a URI and the class type of the listening class. A URI indicates several things. First, the URI type is soap.tcp. This means that it is a URI of a SOAP message sent over TCP. The host name of the URI indicates the computer to listen on, followed by the TCP port number used to listen for incoming connections. In this example, we use port 3131. It is best not to use port numbers under 1000 because they are reserved for specific types of applications (for example, Port 80 is for HTTP servers).
myPeerUri = new Uri ("soap.tcp://" + System.Net.Dns.GetHostName () + ": 3131/rpspeer1"); SoapReceivers.Add (myPeerUri, typeof (PeerService));
It is also easy to send a message to an asynchronous TCP listener. We just create a SoapEnvelope object and use the Setbodyobject method to serialize the object into the body's XML. SoapEnvelope contains a context property that is similar to the Soaprequestcontext and Soapresponsecontext properties used when SOAP interactions with a regular HTTP binding are used. We use it to create the desired Action SOAP header and optional ReplyTo header. We also add the Kerberos token created earlier and use it to encrypt the message. For sending messages, we use the Soapsender class, which corresponds to the class of soapreceiver we used to listen for incoming messages. The Soapsender class gets the endpoint URI in its constructor, and then sends the passed SoapEnvelope to the Send method. The code that sends the peer message is shown below.
Send messagesoapenvelope envelope = new SoapEnvelope (); envelope. Setbodyobject (myplay); envelope. Context.action = new Action (opponenturi.tostring ()); envelope. CONTEXT.SECURITY.TOKENS.ADD (peertoken); envelope. CONTEXT.SECURITY.ELEMENTS.ADD ( new EncryptedData (Peertoken)); envelope. Context.replyto = myPeerUri; Soapsender peerproxy = new Soapsender (this. Opponenturi);p eerproxy.send (envelope);
You can obtain the complete source code for the rock Paper Scissors application from Microsoft Download Center.
Other features of WSE 2.0
With the rock Paper Scissors application, we've studied many of the features of WSE 2.0, but there are many other features. User name tokens can also be integrated with Windows security, such as Kerberos tokens. Because the security context token is supported, you can establish a valid symmetric key to encrypt multiple messages between two endpoints without having to generate a new key for each message. In addition to the security context token, a security Token service is created, which issues a context token for communication between two endpoints.
For message processing, we only discuss the support for sending asynchronous TCP messages, and in fact, support for synchronous requests/responses is just as good. This support uses the Soapmethod property, similar to the WebMethod properties for the. asmx Web service, and the operation is similar. It is also not good to call services in a separate application space, but the Windows message pump (the basis for creating a window application) is also based on sending messages in a separate application space.
One of the more appealing areas of WSE 2.0 is that it has many extensibility points. You can do anything, including from creating your own custom token handlers to adding your own policy support. Like WSE 1.0, you can still extend the scope of the process, but more importantly, how to advance at a higher level and take advantage of existing work.
Summary
In MSDN, there will be more articles that delve into WSE 2.0. We'll discuss policy, security, message processing, and more in depth. Hopefully rock Paper Scissors shows you some of the strange new features of Advanced WEB service support developed using WSE 2.0. And hopefully it will spark your imagination as much as we do, and develop a WEB service application in a new environment.