简体   繁体   中英

Glassfish, EJB3, SOAP web service and basic authentication

I'm setting up a glassfish server with a single EJB3 as a mocked up backend for a POC. Everything was working fine until I went to add some basic authentication. Just plan text userid and password, nothing sophisticated for this job. I added the following annotations to the EJB:

@WebService(name = "Banking", serviceName = "Banking", targetNamespace = BANKING_NAMESPACE)
@DeclareRoles("user")
@Stateless
public class Banking {
    ...

    @RolesAllowed("user")
    @SOAPBinding(parameterStyle = ParameterStyle.BARE)
    @WebMethod(action = BANKING_NAMESPACE + "/logon", operationName = "logon")
    @WebResult(targetNamespace = XmlStrings.BANKING_MODEL_NAMESPACE)
    public LogonResponse logon(@WebParam(targetNamespace = XmlStrings.BANKING_MODEL_NAMESPACE) Logon request) throws WebServiceException {
     ...
    }
}

According to what I've read of EJB3 spec, this is pretty common for doing a SOAP web service.

However when I send this xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mod="http://www.dhcbank.com/banking/model">
    <soapenv:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken wsu:Id="UsernameToken-79" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <wsse:Username>fred</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">fred</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <mod:logon/>
    </soapenv:Body>
</soapenv:Envelope>

I get the following error back as a SOAP fault:

java.lang.Exception: Client not authorized for invocation of public com.dhcbank.www.banking.schema.LogonResponse com.dhcbank.www.banking.Banking.logon(com.dhcbank.www.banking.schema.Logon) throws javax.xml.ws.WebServiceException

And in the glassfish log:

[#|2010-10-10T12:49:27.497+1100|INFO|glassfish3.0.1|javax.enterprise.system.core.security|_ThreadID=41;_ThreadName=http-thread-pool-8080-(2);|JACC Policy Provider: Failed Permission Check, context(BankingEAR/Banking_war_internal)- permission((javax.security.jacc.EJBMethodPermission Banking logon,ServiceEndpoint,com.dhcbank.www.banking.schema.Logon))|#]

In the glassfish admin screens I added a user called fred with a fred password and assigned it to a groups called user. But that didn't work.

I did some more reading which suggested that I create a sun-ejb-jar.xml file and add it to the ear file. So I created it with this content:

<sun-ejb-jar>
    <enterprise-beans>
        <ejb>
            <ejb-name>Banking</ejb-name>
            <webservice-endpoint>
                <port-component-name>Banking</port-component-name>
                    <login-config>
                        <auth-method>BASIC</auth-method>
                        <realm>file</realm>
                </login-config>
            </webservice-endpoint>               
        </ejb>
    </enterprise-beans>
</sun-ejb-jar>

This is as near as I can tell, correct. However I could not find anything that told me what the values of the port-component-name element should be. So I don't know if I've got it right.

Security does still not appear to be working and I cannot figure out why. Does anyone have any experience with this and can point me at what I've got wrong or not done?

I'm assuming your declared role "user" is the same role name in your file realm? if not provide this mapping in your descriptor:

<sun-ejb-jar>
   <security-role-mapping>
     <role-name>user</role-name>
     <group-name>filerealm-group-name</group-name>
   </security-role-mapping>
   ...

I don't think that you're currently creating the appropriate HTTP header for Basic Authentication. I'm not sure how you create the SOAP request but if you're using a JAX-WS client, the JAX-WS FAQ documents the following:

Q. How do I do basic authentication in JAX-WS?

You can do the following:

 HelloService service = new HelloService(); Hello proxy = (service.getHelloPort()); ((BindingProvider)proxy).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "userfoo"); ((BindingProvider)proxy).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "passbar"); 

USERNAME_PROPERTY, PASSWORD_PROPERTY are used primarily for service requests. I think when you instantiate Service, it fetches WSDL and the server is returning 401. You could try any one of the following solutions.

  1. Use java.net.Authenticator class in your client application.
  2. Provide a local access to the WSDL using catalog. There is a catalog sample in the jax-ws distribution.
  3. Configure web.xml to allow GET requests without authentication

And unless I'm wrong, the usernametoken would fit if the webservice expects the authentication in the SOAP header, which is not the case according to your description.

In other words, for me, you're currently not sending the credentials for the BASIC auth.

See also

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM