无法使用Glassfish上的jax-ws进行身份validation

我一直在尝试创建一个使用SSL进行基本身份validation的java服务。 配置SSL非常简单,但配置身份validation更成问题。 每当我尝试调用标有@RolesAllowed注释的方法时,我都会收到以下exception…

Exception in thread "AWT-EventQueue-0" javax.xml.ws.soap.SOAPFaultException: javax.ejb.EJBAccessException at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178) at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111) at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108) at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78) at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:129) at $Proxy30.reverseString(Unknown Source) at securitytestclient.SecurityTestClient.reverseStringSOAP(SecurityTestClient.java:305) at securitytestclient.SecurityTestClient.buttonReverseActionPerformed(SecurityTestClient.java:217) at securitytestclient.SecurityTestClient.access$000(SecurityTestClient.java:20) at securitytestclient.SecurityTestClient$1.actionPerformed(SecurityTestClient.java:72) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener$Actions.actionPerformed(BasicButtonListener.java:303) at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1661) at javax.swing.JComponent.processKeyBinding(JComponent.java:2879) at javax.swing.JComponent.processKeyBindings(JComponent.java:2926) at javax.swing.JComponent.processKeyEvent(JComponent.java:2842) at java.awt.Component.processEvent(Component.java:6282) at java.awt.Container.processEvent(Container.java:2229) at java.awt.Component.dispatchEventImpl(Component.java:4861) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1890) at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:752) at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1017) at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:889) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:717) at java.awt.Component.dispatchEventImpl(Component.java:4731) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Window.dispatchEventImpl(Window.java:2713) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) at java.awt.EventQueue$4.run(EventQueue.java:680) at java.awt.EventQueue$4.run(EventQueue.java:678) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:677) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) 

我的服务器在Glassfish 3上使用JavaEE。它的函数在bean中定义如下……

 package com.intproimp.testing.beans; import javax.annotation.security.PermitAll; import javax.annotation.security.RolesAllowed; import javax.ejb.Local; import javax.ejb.Stateless; @Stateless(mappedName="ejb/StringOps/Bean") @Local(StringOps.class) public class StringOpsBean implements StringOps { @PermitAll @Override public String echoString(String str) { return str; } @RolesAllowed({"admin"}) @Override public String reverseString(String str) { char[] input = str.toCharArray(); char[] output = new char[input.length]; for (int i = 0; i < output.length; i++) { output[i] = input[input.length - i - 1]; } return new String(output); } } 

我已将登录配置添加到我的web.xml文件中……

  BASIC testing-frealm    admin    user  

安全领域只是一个文件域,有一个用户(名称:“andrew”,传递:“12345”)。 我还在我的glassfish-web.xml中添加了角色组映射

  user user   admin admin  

在客户端,我有一个简单的swing应用程序来测试……

摆动测试应用

正在进行的调用是SOAP通道上的反向函数。 SOAP客户端组件是使用NetBeans通过New-> WebService Client函数生成的。 与反向按钮点击相关的操作是……

 private void addAuthenticateionSOAP(StringOpsSOAP port) { ((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, fieldUsername.getText()); ((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, fieldPassword.getText()); } private String reverseStringSOAP(String str) { StringOpsSOAP_Service service = new StringOpsSOAP_Service(); StringOpsSOAP port = service.getStringOpsSOAPPort(); if (checkAuthentication.isSelected()) addAuthenticateionSOAP(port); return port.reverseString(str); } 

我确信我只缺少一些小东西,但我已经看了好几天这个问题,但仍然没有找到它。

– 编辑 – 我意识到可能会有一些混乱,因为我没有发布我的WebService代码。 包含String函数的EJB通过SOAP WebService Bean访问…

 package com.intproimp.test.web; import com.intproimp.test.beans.StringOps; import javax.ejb.EJB; import javax.jws.WebService; import javax.ejb.Stateless; import javax.jws.WebMethod; import javax.jws.WebParam; @WebService(serviceName = "StringOpsSOAP") @Stateless() public class StringOpsSOAP { @EJB private StringOps ops; @WebMethod(operationName = "echoString") public String echoString(@WebParam(name = "str") String str) { return ops.echoString(str); } @WebMethod(operationName = "reverseString") public String reverseString(@WebParam(name = "str") String str) { return ops.reverseString(str); } } 

您需要在web.xml添加 ,其中描述了允许谁访问某个URL。 它在Java EE 6教程中的“ 保护Web应用程序”中进行了描述。 在你的情况下,它应该是这样的:

  WebServiceSecurity  Authorized users only /yoururl POST   user admin  

编辑:如果您通过将@webservice注释添加到类并使用@webmethod发布方法,如果您将无状态会话bean设置为Web服务,这应该可以@webmethod ,正如dma_k在评论中所说的那样。

编辑2:从上面的链接:

指定安全约束

安全约束用于使用URL映射定义对资源集合的访问权限。

进一步:

指定Web资源集合

url-pattern用于列出要保护的请求URI。 许多应用程序都具有不受保护和受保护的资源。 要提供对资源的无限制访问,请不要为该特定请求URI配置安全性约束。

和:

指定授权约束

授权约束建立了对身份validation的要求,并命名授权访问此安全性约束声明的URL模式和HTTP方法的角色。 如果没有授权约束,则容器必须接受请求而不需要用户身份validation。

所以,没有 =>没有身份validation=>没有可用的角色。

使用来自WebServiceContext审计或读取信息( getUserPrincipal()isUserInRole() )来validation这一点。