A.8.2.2.3. STS 实施类

Apache CXF 的 STS SecurityTokenServiceProvider 是符合 WS-Trust 规范中定义的协议和功能的 Web 服务提供商。它具有模块化架构,其组件可配置或可替换。实施和配置插件可以启用可选功能。您可以通过从 SecurityTokenServiceProvider 扩展并覆盖默认设置来自定义自己的 STS。

SampleSTSBearer STS 实施类是从 SecurityTokenServiceProvider 扩展的 POJO。

注意

SampleSTSBearer 类使用 WebServiceProvider 注释来定义,而不是使用 WebService 注释。此注释将服务定义为基于 提供程序的端点,它支持面向消息传递的 Web 服务方法。特别是,它表示交换的消息将是 XML 文档。SecurityTokenServiceProviderjavax.xml.ws.Provider 接口的一种实施。相比之下,WebService 注释定义基于服务端点接口的端点,该端点支持使用 SOAP 信封进行消息交换。

BearerImpl 类中所做的操作,WSS4J 注解 EndpointPropertiesEndpointProperty 为 Apache CXF 运行时提供端点配置。列表中的第一个 EndpointProperty 语句声明了用于消息签名的用户名称。它在密钥存储中用作别名名称,用于获取用户签名的证书和私钥。接下来的两个 EndpointProperty 语句声明包含(Merlin)Crypto 配置信息的 Java 属性文件。在本例中,用于签名和加密消息。WSS4J 读取此文件,以及消息处理所需的信息。最后的 EndpointProperty 语句声明 STSBearerCallbackHandler 实施类。它用于获取密钥存储文件中证书的密码。

在这种实施中,我们自定义令牌规范、令牌验证及其静态属性的操作。

StaticSTSProperties 用于设置用于在 STS 中配置资源的选项。这看起来像是使用 WSS4J 注释进行的设置重复。值相同,但设置的下层结构不同,因此必须在两个位置声明此信息。

setIssuer 设置很重要,因为它唯一地标识了发行的 STS。签发者字符串嵌入了发布的令牌中,在验证令牌时,STS 会检查签发者字符串值。因此,务必要以一致的方式使用签发者字符串,以便 STS 可以识别发布的令牌。

setEndpoints 调用允许按地址声明一组允许的令牌接收者。地址指定为 reg-ex 模式。

TokenIssueOperation 具有一个模块化结构。这允许将自定义行为注入到消息处理中。在本例中,我们将覆盖 SecurityTokenServiceProvider 默认行为并执行 SAML 令牌处理。Apache CXF 提供了 SAMLTokenProvider 的一种实施,它可用于而不是创建 SAMLTokenProvider。

package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer;

import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;

import javax.xml.ws.WebServiceProvider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

@WebServiceProvider(serviceName = "SecurityTokenService",
      portName = "UT_Port",
      targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
      wsdlLocation = "WEB-INF/wsdl/bearer-ws-trust-1.4-service.wsdl")
//dependency on org.apache.cxf module or on module that exports org.apache.cxf (e.g. org.jboss.ws.cxf.jbossws-cxf-client) is needed, otherwise Apache CXF annotations are ignored
@EndpointProperties(value = {
      @EndpointProperty(key = "ws-security.signature.username", value = "mystskey"),
      @EndpointProperty(key = "ws-security.signature.properties", value = "stsKeystore.properties"),
      @EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer.STSBearerCallbackHandler")
})
public class SampleSTSBearer extends SecurityTokenServiceProvider {

   public SampleSTSBearer() throws Exception {
      super();

      StaticSTSProperties props = new StaticSTSProperties();
      props.setSignatureCryptoProperties("stsKeystore.properties");
      props.setSignatureUsername("mystskey");
      props.setCallbackHandlerClass(STSBearerCallbackHandler.class.getName());
      props.setEncryptionCryptoProperties("stsKeystore.properties");
      props.setEncryptionUsername("myservicekey");
      props.setIssuer("DoubleItSTSIssuer");

      List<ServiceMBean> services = new LinkedList<ServiceMBean>();
      StaticService service = new StaticService();
      service.setEndpoints(Arrays.asList(
         "https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService",
         "https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService",
         "https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService"
      ));
      services.add(service);

      TokenIssueOperation issueOperation = new TokenIssueOperation();
      issueOperation.getTokenProviders().add(new SAMLTokenProvider());
      issueOperation.setServices(services);
      issueOperation.setStsProperties(props);
      this.setIssueOperation(issueOperation);
   }
}