访问受保护的 JAX-WS EJB 网络服务
Accessing secured JAX-WS EJB webservice
如何访问这个由 EJB 实现的安全 Soap Web 服务:
@Stateless
@DeclareRoles({"Boss"})
@WebService(name="SoapService", serviceName="SoapWS", portName="SoapWSPort")
public class SoapServiceImpl implements SoapService {
@RolesAllowed({"Boss"})
public SoapThing getSoapThing(String name, String prepend) throws SoapThingyException {
...
}
}
而 web.xml 有这个:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>ApplicationRealm</realm-name>
</login-config>
我为客户端创建了一个 SoapHandler,为请求添加授权 header,如下所示:
public boolean handleMessage(SOAPMessageContext context) {
try {
String credential = Base64.getEncoder().encodeToString((username+":"+password).getBytes("UTF-8"));
Map<String, Object> httpHeaders = null;
if (context.get(MessageContext.HTTP_REQUEST_HEADERS) != null) {
httpHeaders = (Map<String, Object>)context.get(MessageContext.HTTP_REQUEST_HEADERS);
} else {
httpHeaders = new HashMap<>();
}
httpHeaders.put("Authorization", Arrays.asList("Basic " + credential.substring(0, credential.length()-1)));
context.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
return true;
} catch (UnsupportedEncodingException e) {
return false;
}
}
我的客户端是一个独立的 java 应用程序,使用 wsimport 生成的存根,并将处理程序添加到 BindingProvider:
SoapWS service = new SoapWS();
SoapService port = service.getSoapWSPort();
((BindingProvider)port).getBinding().setHandlerChain(Arrays.asList(new CredentialHandler("spike", "*****")));
SoapThing st = port.getSoapThingByNumber(1);
...它执行得很好,将凭据添加到授权 header 但我仍然从服务器收到未经授权的响应:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized
Web 服务部署在 Wildfly 上,用户被分配到 ApplicationRealm,角色 Administator,组 Dog 和 Boss:
我错过了什么?
在 JAX-WS 客户端中使用基本身份验证比这更容易:
SoapWS service = new SoapWS();
SoapService port = service.getSoapWSPort();
Map<String,Object> requestContext = ((BindingProvider)port).getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);
SoapThing st = port.getSoapThingByNumber(1);
不需要处理程序。
JAX-WS 客户端机器自动处理 HTTP 401 质询。
如何访问这个由 EJB 实现的安全 Soap Web 服务:
@Stateless
@DeclareRoles({"Boss"})
@WebService(name="SoapService", serviceName="SoapWS", portName="SoapWSPort")
public class SoapServiceImpl implements SoapService {
@RolesAllowed({"Boss"})
public SoapThing getSoapThing(String name, String prepend) throws SoapThingyException {
...
}
}
而 web.xml 有这个:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>ApplicationRealm</realm-name>
</login-config>
我为客户端创建了一个 SoapHandler,为请求添加授权 header,如下所示:
public boolean handleMessage(SOAPMessageContext context) {
try {
String credential = Base64.getEncoder().encodeToString((username+":"+password).getBytes("UTF-8"));
Map<String, Object> httpHeaders = null;
if (context.get(MessageContext.HTTP_REQUEST_HEADERS) != null) {
httpHeaders = (Map<String, Object>)context.get(MessageContext.HTTP_REQUEST_HEADERS);
} else {
httpHeaders = new HashMap<>();
}
httpHeaders.put("Authorization", Arrays.asList("Basic " + credential.substring(0, credential.length()-1)));
context.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
return true;
} catch (UnsupportedEncodingException e) {
return false;
}
}
我的客户端是一个独立的 java 应用程序,使用 wsimport 生成的存根,并将处理程序添加到 BindingProvider:
SoapWS service = new SoapWS();
SoapService port = service.getSoapWSPort();
((BindingProvider)port).getBinding().setHandlerChain(Arrays.asList(new CredentialHandler("spike", "*****")));
SoapThing st = port.getSoapThingByNumber(1);
...它执行得很好,将凭据添加到授权 header 但我仍然从服务器收到未经授权的响应:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized
Web 服务部署在 Wildfly 上,用户被分配到 ApplicationRealm,角色 Administator,组 Dog 和 Boss:
我错过了什么?
在 JAX-WS 客户端中使用基本身份验证比这更容易:
SoapWS service = new SoapWS();
SoapService port = service.getSoapWSPort();
Map<String,Object> requestContext = ((BindingProvider)port).getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);
SoapThing st = port.getSoapThingByNumber(1);
不需要处理程序。
JAX-WS 客户端机器自动处理 HTTP 401 质询。