the handler for exracting the login name? that's basically the code i
included below to extract from the incoming message, then create the user
object, hit the LDAP server (through JNDI api) and then store (actually in a
thread-local so even non-Axis code can get the current user). the rest is to
include it thus in your server-config.wsdd:
<service name="FreezerWS" provider="java:RPC" style="document" use="literal">
<!-- WS-Security handlers -->
<requestFlow>
<!-- the header that carries the user's login-name -->
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="action" value="UsernameToken"/>
<parameter name="actor" value="loginName"/>
<parameter name="passwordCallbackClass" value="ServerSidePWCallback"/>
</handler>
<!-- add a handler that populates the session given the user's
login-name -->
<handler
type="java:com.amgen.seattle.appdev.freezer.webservice.server.WSLoginNameHandler">
<!-- the actor of the UsernameToken header with the login-name -->
<parameter name="headerActor" value="loginName"/>
</handler>
</requestFlow>
that's about it.
the best documentation on WSS4J (or at least links to it) SHOULD be in the
Wiki ( http://wiki.apache.org/ws/FrontPage/WsFx ) but i'm not certain one
could say that yet... i keep a short list of good resources i've found here
http://wiki.apache.org/ws/RonReynolds/Wss4jLinks but it's only a handful of
links but it might give you a starting point. :) search around in the Wiki
and then your next best bet are the 2 wss4j docs and then Google...
..................ron.
> Thx for your help. I figured it out now. Didnt see one section of the
> WSS4J documentation. You can set the EngineConfiguration to use a wsdd
> file inside the program code. As long as this is readable from the
> servlet everythings fine.
> Is there any good tutorial or documentation on developing these Handlers
> like you explained below? I dunno if you mind sharing your Handler
> implementation. It would be interesting to see how you did this.
> Thanks alot!
> Michael
>
>>i haven't tried this. it certainly must be possible, but right now i haven't
>>the time to figure it out.
>>
>>i would start at MessageContext.getAxisEngine().getGlobalRequest() and search
>>in that area. the file itself is loaded by
>>org.apache.axis.configuration.EngineConfigurationFactoryDefault. also i seem
>>to remember someone mentioning that you could access the global request flow
>>and insert a handler into that flow at runtime. also if you have permissions
>>you can call System.setProperty() from a startup servlet (if you want a
>>possibly much simpler solution that opens up a bunch of possible bugs if
>>another servlet in the same servlet engine tries to connect to a different
>> web
>>service...)
>>
>>sorry i couldn't be of more help. :-/
>>...............ron.
>>
>>
>>
>>
>>>Ok...i dont use the client_deploy.wsdd....is there any way to avoid
>>>using it? I have the client inside a servlet so i cant specify it with
>>>the java -D.... command line.
>>>Thx!
>>>Michael
>>>
>>>
>>>
>>>>do you have this in your client-config.wsdd?
>>>><deployment ...>
>>>> <transport .../>
>>>> <globalConfiguration>
>>>> <requestFlow>
>>>> <!-- add the header that carries the user's login-name -->
>>>> <handler type="java:org.apache.ws.axis.security.WSDoAllSender">
>>>> <parameter name="action" value="UsernameToken"/>
>>>> <parameter name="actor" value="loginName"/>
>>>> <parameter name="passwordCallbackClass" value="PWCallback"/>
>>>> </handler>
>>>>?
>>>>
>>>>otherwise there won't be any handler in the request flow that knows what to
>>>>do
>>>>with those properties.
>>>>
>>>>hth.
>>>>.............ron.
>>>>
>>>>
>>>>
>>>>
>>>>>Ok, so i got the server working basically (i think) but when calling it
>>>>>i get the following exception at the client:
>>>>>
>>>>>AxisFault
>>>>>faultCode:
>>>>>{http://schemas.xmlsoap.org/soap/envelope/}Server.generalException
>>>>>faultSubcode:
>>>>>faultString: WSDoAllReceiver: Request does not contain required
>>>>>Security header
>>>>>
>>>>>
>>>>>Thats the client code so far:
>>>>>
>>>>>try {
>>>>> binding = new al.JCT.service.JCTServiceLocator().getJCTSession();
>>>>> Stub axisPort = (Stub)binding;
>>>>> axisPort._setProperty(UsernameToken.PASSWORD_TYPE,
>>>>>WSConstants.PASSWORD_DIGEST);
>>>>> axisPort._setProperty(WSHandlerConstants.USER, "wss4j");
>>>>> axisPort._setProperty(WSHandlerConstants.PW_CALLBACK_REF, new
>>>>>PWCallback());
>>>>> }
>>>>> catch (javax.xml.rpc.ServiceException jre) {
>>>>> jre.printStackTrace();
>>>>> return;
>>>>> }
>>>>>
>>>>> try {
>>>>> al.JCT.service.Job[] value = null;
>>>>> String ids[] = {"1218"};
>>>>> value = binding.getJobStatus("rudi", "qw", null, ids);
>>>>> if (value != null) {
>>>>> for (int i=0; i < value.length; i++) {
>>>>> System.out.println(value[i].getId() + " - " +
>>>>>value[i].getName() + " - " + value[i].getPe());
>>>>> System.out.println(value[i].getReservations());
>>>>> System.out.println(value[i].getOutputPaths()[0].getPath());
>>>>> }
>>>>> }
>>>>> binding.submitJob(null, null, null);
>>>>> }
>>>>> catch (java.rmi.RemoteException re) {
>>>>> re.printStackTrace();
>>>>> return;
>>>>> }
>>>>>
>>>>>
>>>>>Any ideas on this one?
>>>>>
>>>>>Thx!
>>>>>Michael
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>you can extract all the security info by looking at the Vector stored
>>>>>>as a property in the MessageContext:
>>>>>>Vector resultHandlers =
>>>>>>(Vector)MessageContext.getCurrentContext().getProperty(WSHandlerConstants.RECV_RESULTS);
>>>>>>
>>>>>>
>>>>>>this vector contains, as far as i can tell, everything you could want
>>>>>>to know.
>>>>>>or you can extract the username from the message itself -
>>>>>>ArrayList actorList = new ArrayList();
>>>>>>actorList.add("actor value for my UsernameToken entry");
>>>>>>Message request = MessageContext.getCurrentContext().getRequestMessage();
>>>>>>SOAPEnvelope envelope = (SOAPEnvelope)request.getSOAPEnvelope();
>>>>>>Vector headers = envelope.getHeadersByActor(actorList);
>>>>>>SOAPHeaderElement header = (SOAPHeaderElement)headers.get(0);
>>>>>>
>>>>>>you can then extract the actual username by walking the DOM tree to
>>>>>>the node which contains the username
>>>>>>MessageElement usernameTokenElement =
>>>>>>header.getChildElement(USERNAME_TOKEN_QNAME);
>>>>>>MessageElement usernameElement =
>>>>>>usernameTokenElement.getChildElement(USERNAME_QNAME);
>>>>>>String username = usernameElement.getValue();
>>>>>>
>>>>>>(you'll also need these)
>>>>>>static final QName USERNAME_TOKEN_QNAME = new
>>>>>>QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN);
>>>>>>static final QName USERNAME_QNAME = new QName(WSConstants.WSSE_NS,
>>>>>>WSConstants.USERNAME_LN);
>>>>>>
>>>>>>in my app i have a handler which i put in the request chain right
>>>>>>after the WSDoAllReceiver which extracts the username using the above
>>>>>>code, does an LDAP lookup of the user to gather roles, and then
>>>>>>creates an app-specific user object which it stores it as a properly
>>>>>>in the MessageContext where anyone in the handling chain can then
>>>>>>extract it via getProperty().
>>>>>>
>>>>>>hth.
>>>>>>......................ron.
>>>>>>
>>>>>>Michael Rudolf wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>Thanks a lot for the detailed description! I think this will work
>>>>>>>fine for me. One more question about this though: Can i read the
>>>>>>>username inside the web service? Or is there any way of getting
>>>>>>>information like the group a user belongs to inside the web service
>>>>>>>to read it there? It sounds like the Service does get any of this
>>>>>>>info since the authentication is completely transparent to the
>>>>>>>service itself.
>>>>>>>Thanks.
>>>>>>>Michael
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>>by "Web Services are made out of Session EJBs" you mean you have
>>>>>>>>Session EJBs that expose a SOAP-over-HTTP interface? WSS4J uses 2
>>>>>>>>handlers, one client-side and one server-side (WSDoAllSender
>>>>>>>>(client) and WSDoAllReceiver (server)) which plug into the handler
>>>>>>>>chain supported by Axis to "intercept" the request on its way to the
>>>>>>>>server. WSDoAllSender adds a WSSecurity header to the SOAP message
>>>>>>>>on send (configured using a properties file). WSDoAllReceiver then
>>>>>>>>processes the incoming message, validates whatever it's configured
>>>>>>>>to validate and then passes the request on to your handlers/service
>>>>>>>>(or rejects the message if it does not validate properly). to add
>>>>>>>>UsernameTokens to a request and process them on the server requires
>>>>>>>>a CallbackHandler on the client side which can provide the password
>>>>>>>>for a user. this is then processed into a UsernameToken, included
>>>>>>>>in the SOAP header, and on the server side you'll need another
>>>>>>>>CallbackHandler which can provide the password for the user (pulled
>>>>>>>>
>>>>>>>>
>>>>>>>>from LDAP) which WSS4J will compare to what's provided in the
>>>>>>>
>>>>>>>
>>>>>>>>UsernameToken and thus authenicate the message before your service
>>>>>>>>(however it's implemented) ever gets called. it's quite transparent
>>>>>>>>for the most part. it also inserts a few entries in the
>>>>>>>>MessageContext so you can later determine what kind of authenication
>>>>>>>>has been done.
>>>>>>>>
>>>>>>>>hth.
>>>>>>>>.......................ron.
>>>>>>>>Michael Rudolf wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>>Is there any difference in case the Web Services are made out of
>>>>>>>>>Session EJBs? Or does WSS4J work the same way in that case?
>>>>>>>>>Thanks!
>>>>>>>>>Michael
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>you may want to look at WSS4J and UsernameTokens. they're pretty
>>>>>>>>>>straight-forward as long as your client can support them. they
>>>>>>>>>>are part of
>>>>>>>>>>the WS-Security standard if you want to stick with "endorsed"
>>>>>>>>>>authentication
>>>>>>>>>>mechanisms. then on the server-side you'll typically need a JNDI
>>>>>>>>>>interface to
>>>>>>>>>>your LDAP server to authenticate the user on that side.
>>>>>>>>>>
>>>>>>>>>>hth.
>>>>>>>>>>................ron.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>Hi,
>>>>>>>>>>>is there any tutorial or example for authenticating users of we
>>>>>>>>>>>services
>>>>>>>>>>>by username and pass over HTTPS? Can anybody explain in more
>>>>>>>>>>>detail how
>>>>>>>>>>>this works? Is there any alternative to it? I want to query axis web
>>>>>>>>>>>sercvices from a portal. That uses LDAP for authetication. I
>>>>>>>>>>>would like
>>>>>>>>>>>to use the same directory for authenticating the users at the web
>>>>>>>>>>>services that are being queried.
>>>>>>>>>>>Thanks for any help!
>>>>>>>>>>>Michael
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>>
>>
>>
>>
>
>