A.8.3. 场景:OnehalfOf WS-Trust
OnBehalfOf 功能用于使用代理模式的情况。在这种情况下,客户端无法直接访问 STS,而是通过代理网关进行通信。代理网关验证调用者,并将调用者的信息放入 RequestSecurityToken (RST)的 OnBehalfOf 元素中,以用于处理。生成的令牌仅包含与代理客户端相关的声明,使代理对颁发的令牌的接收器完全透明。
OnBehalfOf 不仅仅是 RST 中的新子元素。它在与 STS 协商令牌时提供有关原始调用者的额外信息。OnBehalfOf 元素通常采用令牌形式,其身份声明(如名称、角色和授权代码)供客户端访问服务。
OnBehalfOf 方案是基本 WS-Trust 场景的扩展。在本例中,OnBehalfOf 服务代表用户调用 ws-service。对基本场景的代码仅作几处补充。添加了 OnBehalfOf Web 服务提供商和回调处理程序。OnBehalfOf Web 服务的 WSDL 采用了与 ws-provider 相同的安全策略。UsernameTokenCallbackHandler 是与 ActAs 共享的实用程序。它为 OnBehalfOf 元素生成内容。最后,STS 中也添加了代码,OnBehalfOf 和 ActAs 共享了相同的代码。
A.8.3.1. Web 服务提供商 复制链接链接已复制到粘贴板!
本节提供已更新的基本 WS-Trust 场景中的 Web 服务元素,以满足 OnBehalfOf 示例 的要求。这些组件包括:
A.8.3.1.1. Web 服务提供商 WSDL 复制链接链接已复制到粘贴板!
OnBehalfOf Web 服务提供商的 WSDL 是 ws-provider 的 WSDL 的 克隆。wsp:Policy 部分是相同的。对服务端点、target Namespace、portType、绑定 名称和 服务进行了更新。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" name="OnBehalfOfService"
xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsaws="http://www.w3.org/2005/08/addressing"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<types>
<xsd:schema>
<xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
schemaLocation="OnBehalfOfService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"/>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"/>
</message>
<portType name="OnBehalfOfServiceIface">
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
</portType>
<binding name="OnBehalfOfServicePortBinding" type="tns:OnBehalfOfServiceIface">
<wsp:PolicyReference URI="#AsymmetricSAML2Policy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Input_Policy" />
</input>
<output>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Output_Policy" />
</output>
</operation>
</binding>
<service name="OnBehalfOfService">
<port name="OnBehalfOfServicePort" binding="tns:OnBehalfOfServicePortBinding">
<soap:address location="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService"/>
</port>
</service>
</definitions>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" name="OnBehalfOfService"
xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsaws="http://www.w3.org/2005/08/addressing"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<types>
<xsd:schema>
<xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
schemaLocation="OnBehalfOfService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"/>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"/>
</message>
<portType name="OnBehalfOfServiceIface">
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
</portType>
<binding name="OnBehalfOfServicePortBinding" type="tns:OnBehalfOfServiceIface">
<wsp:PolicyReference URI="#AsymmetricSAML2Policy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Input_Policy" />
</input>
<output>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Output_Policy" />
</output>
</operation>
</binding>
<service name="OnBehalfOfService">
<port name="OnBehalfOfServicePort" binding="tns:OnBehalfOfServicePortBinding">
<soap:address location="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService"/>
</port>
</service>
</definitions>
A.8.3.1.2. Web 服务提供商接口 复制链接链接已复制到粘贴板!
OnBehalfOfServiceIface Web 服务提供商接口类是一个简单的 Web 服务定义。
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
)
public interface OnBehalfOfServiceIface {
@WebMethod
String sayHello();
}
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
)
public interface OnBehalfOfServiceIface {
@WebMethod
String sayHello();
}
A.8.3.1.3. Web 服务提供商实施 复制链接链接已复制到粘贴板!
OnBehalfOfServiceImpl Web 服务提供商实施类是一个简单的 POJO。它使用标准的 WebService 注释来定义服务端点和两个 Apache WSS4J 注释,即 EndpointProperties 和 EndpointProperty,用于为 Apache CXF 运行时配置端点。提供的 WSS4J 配置信息用于 WSS4J 的 Crypto Merlin 实施。
OnBehalfOfService 。Impl 代表用户调用 ServiceImplsetupService 方法执行所需的配置设置。
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.trust.STSClient;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import java.net.*;
import java.util.Map;
@WebService
(
portName = "OnBehalfOfServicePort",
serviceName = "OnBehalfOfService",
wsdlLocation = "WEB-INF/wsdl/OnBehalfOfService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfServiceIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"),
@EndpointProperty(key = "ws-security.signature.properties", value = "actasKeystore.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value = "actasKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfCallbackHandler")
})
public class OnBehalfOfServiceImpl implements OnBehalfOfServiceIface {
public String sayHello() {
try {
ServiceIface proxy = setupService();
return "OnBehalfOf " + proxy.sayHello();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
/**
*
* @return
* @throws MalformedURLException
*/
private ServiceIface setupService()throws MalformedURLException {
ServiceIface proxy = null;
Bus bus = BusFactory.newInstance().createBus();
try {
BusFactory.setThreadDefaultBus(bus);
final String serviceURL = "http://" + WSTrustAppUtils.getServerHost() + ":8080/jaxws-samples-wsse-policy-trust/SecurityService";
final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", "SecurityService");
final URL wsdlURL = new URL(serviceURL + "?wsdl");
Service service = Service.create(wsdlURL, serviceName);
proxy = (ServiceIface) service.getPort(ServiceIface.class);
Map<String, Object> ctx = ((BindingProvider) proxy).getRequestContext();
ctx.put(SecurityConstants.CALLBACK_HANDLER, new OnBehalfOfCallbackHandler());
ctx.put(SecurityConstants.SIGNATURE_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"actasKeystore.properties" ));
ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myactaskey" );
ctx.put(SecurityConstants.ENCRYPT_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"../../META-INF/clientKeystore.properties" ));
ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey");
STSClient stsClient = new STSClient(bus);
Map<String, Object> props = stsClient.getProperties();
props.put(SecurityConstants.USERNAME, "bob");
props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey");
props.put(SecurityConstants.STS_TOKEN_USERNAME, "myactaskey" );
props.put(SecurityConstants.STS_TOKEN_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"actasKeystore.properties" ));
props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true");
ctx.put(SecurityConstants.STS_CLIENT, stsClient);
} finally {
bus.shutdown(true);
}
return proxy;
}
}
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.trust.STSClient;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import java.net.*;
import java.util.Map;
@WebService
(
portName = "OnBehalfOfServicePort",
serviceName = "OnBehalfOfService",
wsdlLocation = "WEB-INF/wsdl/OnBehalfOfService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfServiceIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"),
@EndpointProperty(key = "ws-security.signature.properties", value = "actasKeystore.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value = "actasKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfCallbackHandler")
})
public class OnBehalfOfServiceImpl implements OnBehalfOfServiceIface {
public String sayHello() {
try {
ServiceIface proxy = setupService();
return "OnBehalfOf " + proxy.sayHello();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
/**
*
* @return
* @throws MalformedURLException
*/
private ServiceIface setupService()throws MalformedURLException {
ServiceIface proxy = null;
Bus bus = BusFactory.newInstance().createBus();
try {
BusFactory.setThreadDefaultBus(bus);
final String serviceURL = "http://" + WSTrustAppUtils.getServerHost() + ":8080/jaxws-samples-wsse-policy-trust/SecurityService";
final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", "SecurityService");
final URL wsdlURL = new URL(serviceURL + "?wsdl");
Service service = Service.create(wsdlURL, serviceName);
proxy = (ServiceIface) service.getPort(ServiceIface.class);
Map<String, Object> ctx = ((BindingProvider) proxy).getRequestContext();
ctx.put(SecurityConstants.CALLBACK_HANDLER, new OnBehalfOfCallbackHandler());
ctx.put(SecurityConstants.SIGNATURE_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"actasKeystore.properties" ));
ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myactaskey" );
ctx.put(SecurityConstants.ENCRYPT_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"../../META-INF/clientKeystore.properties" ));
ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey");
STSClient stsClient = new STSClient(bus);
Map<String, Object> props = stsClient.getProperties();
props.put(SecurityConstants.USERNAME, "bob");
props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey");
props.put(SecurityConstants.STS_TOKEN_USERNAME, "myactaskey" );
props.put(SecurityConstants.STS_TOKEN_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"actasKeystore.properties" ));
props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true");
ctx.put(SecurityConstants.STS_CLIENT, stsClient);
} finally {
bus.shutdown(true);
}
return proxy;
}
}
A.8.3.1.4. OnBehalfOfCallbackHandler Class 复制链接链接已复制到粘贴板!
OnBehalfOfCallbackHandler 是 WSS4J Crypto API 的回调处理程序。它用于在密钥存储中获取私钥的密码。此类使 Apache CXF 能够检索用于消息签名的用户名密码。此类已被更新,返回此服务的密码 myactaskey 和 OnBehalfOf 用户 alice。
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
public class OnBehalfOfCallbackHandler extends PasswordCallbackHandler {
public OnBehalfOfCallbackHandler() {
super(getInitMap());
}
private static Map<String, String> getInitMap() {
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("myactaskey", "aspass");
passwords.put("alice", "clarinet");
passwords.put("bob", "trombone");
return passwords;
}
}
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
public class OnBehalfOfCallbackHandler extends PasswordCallbackHandler {
public OnBehalfOfCallbackHandler() {
super(getInitMap());
}
private static Map<String, String> getInitMap() {
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("myactaskey", "aspass");
passwords.put("alice", "clarinet");
passwords.put("bob", "trombone");
return passwords;
}
}