|
In less than 10 minutes I just created a VB.NET demo for an upcoming SearchVB.com webcast, using WSE 2.0. Policy rocks! However...even though I've been through this before, once again I was momentarily baffled by the fact that my service seemed to be authorizing my UsernameToken even though I submitted a bad password. Well, that's the policy cache baby!
Steps to create the sample:
- Create a Web service project, enable WSE 2.0 extensions for the service
- Add a custom UsernameTokenManager class to handle, well, UsernameToken authentication.
- Add code to authenticate by performing a database lookup and returning the password from the AuthenticateToken method. In this case, I'm just returning password, clearly not a real example.
Public Class CustomUsernameTokenManager Inherits UsernameTokenManager
Protected Overrides Function AuthenticateToken(ByVal token As UsernameToken) As String Return GetUserPassword(token) End Function
End Class
Even without specifying a service side policy that requires a UsernameToken, the UsernameTokenManager will be invoked on each request and will validate the <wsse:UsernameToken> element passed with any requests. You should specify a policy as a best practice
- Create a Windows Forms client, add WSE 2.0 support BEFORE you add a Web reference to the Web service just created. This ensures that you get a WSE-aware proxy class.
- Add a couple of textboxes and a button to the Form, and handle the button click event by creating an instance of the WSE-enabled proxy, and invoking the service.
- Create a policy for the client to require UsernameToken signature
- Add code BEFORE invoking the WebMethod to create a UsernameToken object, and add it to the policy cache. Note: Here you'll notice that I'm clearing the cache before adding the token to the cache. This is where you'll run into trouble since the cache is not cleared unless you explicitly clear it.
Dim svc As New localhost.Service1Wse Dim userToken As New UsernameToken(Me.TextBox1.Text, Me.TextBox2.Text, PasswordOption.SendNone)
PolicyEnforcementSecurityTokenCache.GlobalCache.Clear() PolicyEnforcementSecurityTokenCache.GlobalCache.Add(userToken) Dim s As String = svc.GetSecret()
This brings up an interesting point about the policy cache. When should you populate it? When should it be cleared? Should we create policy cache managers that handle updating existing tokens when a new password is supplied?
Of course, this is a demo, so on most occasions, we wouldn't happily modifying passwords for the same user during the same session. However, a new UsernameToken is still added to the cache even if it refers to the same user, so beware of a) bloating the cache with tokens, and b) sending the wrong token (the first on in the cache wins!). In short, based on your client application, determine an efficient way to keep the cache free of junk. Perhaps store the token in the cache at login time, and reuse that token for each Web service request.
|