Securing a service endpoint
First we secure the access to the SLSB as we would do for normal (non web service) invocations.
In ejb-jar.xml, we setup the method permissions for the SLSB endpoint. Note that it is not necessary required for the endpoint to have home/remote interfaces.
<enterprise-beans> <session> <ejb-name>SecuredSLSB</ejb-name> <remote>com.underworld.crimeportal.ejb.SecuredRemote</remote> <home>com.underworld.crimeportal.ejb.SecuredRemoteHome</home> <service-endpoint>com.underworld.crimeportal.OrganizationEndpoint</service-endpoint> <ejb-class>com.underworld.crimeportal.ejb.SecuredSLSB</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <security-role-ref> <role-name>friend</role-name> </security-role-ref> </session> </enterprise-beans> <assembly-descriptor> <security-role> <role-name>friend</role-name> </security-role> <method-permission> <role-name>friend</role-name> <method> <ejb-name>SecuredSLSB</ejb-name> <method-name>*</method-name> </method> </method-permission> </assembly-descriptor>
Next, define the security domain for this deployment. The JBossWS security context is configured in login-config.xml and uses the UsersRolesLoginModule.
<jboss> <security-domain>java:/jaas/JBossWS</security-domain> <enterprise-beans> <session> <ejb-name>SecuredSLSB</ejb-name> <jndi-name>ejb/SecuredSLSB</jndi-name> </session> </enterprise-beans> </jboss>
At last, make sure that your WSDL files point to the right url. Otherwise your webservice client may be redirected to the unsecure HTTP access method. The easiest way is to add "https://" to the SOAP Address entry:
<soap:address location="https://REPLACE_WITH_ACTUAL_URL"></soap:address>
At this point you might want to check that the JRMI access to the SLSB is actually secured.
Use JAXRPC to set principal/credential
A web service client may use the javax.xml.rpc.Stub object to set the username/password combination
public void testWebServiceAccess() throws Exception { OrganizationEndpoint endpoint = service.getPort(OrganizationEndpoint.class); Stub stub = (Stub)endpoint; stub._setProperty(Stub.USERNAME_PROPERTY, "kermit"); stub._setProperty(Stub.PASSWORD_PROPERTY, "thefrog"); String info = endpoint.getContactInfo("mafia"); assertEquals("The 'mafia' boss is currently out of office, please call again.", info); }
Note, that this approach uses SOAP headers to propagate the pricipal/credential information to the server. The headers themselves are JBoss specific and therefore not interoperable with other Web Services implementations out of the box.
<soapenv:Envelope ...> <soapenv:Header xmlns:jbws="http://webservice.jboss.com/ws4ee"> <jbws:username actor="http://webservice.jboss.com/ws4ee/login">kermit</jbws:username> <jbws:password actor="http://webservice.jboss.com/ws4ee/login">dGhlZnJvZw==</jbws:password> </soapenv:Header> <soapenv:Body> <ns1:getContactInfo xmlns:ns1="http://com.underworld.crimeportal"> <String_1>mafia</String_1> </ns1:getContactInfo> </soapenv:Body> </soapenv:Envelope>
Using HTTP Basic Auth for security
An alternative to the SOAP headers, is generic HTTP authentication, which is supported by most Web services toolkits. To enable this you need to add a port-component descriptor to your jboss.xml file, which contains an auth-method tag. We just modify the jboss.xml in the example above to end up with the following result.
<jboss> <security-domain>java:/jaas/JBossWS</security-domain> <enterprise-beans> <session> <ejb-name>SecuredSLSB</ejb-name> <jndi-name>ejb/SecuredSLSB</jndi-name> <port-component> <port-component-name>OrganizationEndpoint</port-component-name> <port-component-uri>/organization/*</port-component-uri> <auth-method>BASIC</auth-method> </port-component> </session> </enterprise-beans> </jboss>
Requiring SSL
You can also require that all webservice requests use SSL by adding the transport-guarantee tag in your jboss.xml file. We will now modify our HTTP basic auth example jboss.xml file to also require that SSL is used.
<jboss> <security-domain>java:/jaas/JBossWS</security-domain> <enterprise-beans> <session> <ejb-name>SecuredSLSB</ejb-name> <jndi-name>ejb/SecuredSLSB</jndi-name> <port-component> <port-component-name>OrganizationEndpoint</port-component-name> <port-component-uri>/orgainization/*</port-component-uri> <auth-method>BASIC</auth-method> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </port-component> </session> </enterprise-beans> </jboss>
Note: If your hostname does not match the ssl certificate name, you have to implement your own
HostnameVerifier
and make it the default
HostnameVerifier
via
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier()
.
Setting the system property
org.jboss.security.ignoreHttpsHost
to true does not work for JBossWS4EE!
Comments