ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Web Services Manager拡張可能アプリケーションの開発
12c (12.1.2)
E48046-02
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

3 サンプル・カスタム・アサーションによる手順

この章では、サンプル・カスタム・アサーションについて説明します。次の項目について説明します。

3.1 概要

この章では、サンプル・カスタム・アサーションについて説明し、各カスタム・アサーションのサンプル・コードを示します。各サンプルには、サンプルに実装されている主な機能について説明するセクションも含まれています。

3.2 IPアドレス検証のカスタム・アサーションのサンプル

IP検証のカスタム・アサーションのサンプルでは、Webサービスに対して実行されたリクエストが、有効なIPアドレスから実行されたかどうかを検証します。カスタム・ポリシー・アサーションでは、有効なIPアドレスをカンマ区切りの値のリストとして含めることができます。他のIPアドレスから来る任意のリクエストは、FAILED_CHECKレスポンスになります。

次の各項では、カスタム・アサーションをコード化する方法を示すサンプルを説明します。

3.2.1 コード・サンプル

この項では、カスタム・アサーションを作成および実装する次のサンプル・コードを示します。

サンプル・カスタム・アサーション・エグゼキュータ

例3-1は、IPアドレスを検証するために使用できるサンプルのカスタム・アサーション・エグゼキュータを示しています。

例3-1 サンプルのカスタム・アサーション・エグゼキュータ

package sampleassertion;
 
import oracle.wsm.common.sdk.IContext;
import oracle.wsm.common.sdk.IMessageContext;
import oracle.wsm.common.sdk.IResult;
import oracle.wsm.common.sdk.Result;
import oracle.wsm.common.sdk.WSMException;
import oracle.wsm.policy.model.IAssertionBindings;
import oracle.wsm.policy.model.IConfig;
import oracle.wsm.policy.model.IPropertySet;
import oracle.wsm.policy.model.ISimpleOracleAssertion;
import oracle.wsm.policy.model.impl.SimpleAssertion;
import oracle.wsm.policyengine.impl.AssertionExecutor;
 
public class IpAssertionExecutor extends AssertionExecutor {
 
    public IpAssertionExecutor() {
    }
 
    public void destroy() {
    }
 
    public void init(oracle.wsm.policy.model.IAssertion assertion,
                     oracle.wsm.policyengine.IExecutionContext econtext,
                     oracle.wsm.common.sdk.IContext context) {
        this.assertion = assertion;
        this.econtext = econtext;
    }
 
    public oracle.wsm.policyengine.IExecutionContext getExecutionContext() {
        return this.econtext;
    }
 
    public boolean isAssertionEnabled() {
        return ((ISimpleOracleAssertion)this.assertion).isEnforced();
    }
 
    public String getAssertionName() {
        return this.assertion.getQName().toString();
    }
 
    /**
     * @param context
     * @return
     */
    public IResult execute(IContext context) throws WSMException {
        try {
         oracle.wsm.common.sdk.IMessageContext.STAGE stage =
 ((oracle.wsm.common.sdk.IMessageContext)context).getStage();
 
            if (stage  == IMessageContext.STAGE.request)  {    
 

               IAssertionBindings bindings =
 ((SimpleAssertion)(this.assertion)).getBindings();
               IConfig config = bindings.getConfigs().get(0);
               IPropertySet propertyset = config.getPropertySets().get(0);
               String valid_ips = propertyset.getPropertyByName("valid_
ips").getValue();
               String ipAddr = ((IMessageContext)context).getRemoteAddr();
               IResult result = new Result();
 
               if (valid_ips != null && valid_ips.trim().length() > 0) {
                    String[] valid_ips_array = valid_ips.split(",");
                    boolean isPresent = false;
                    for (String valid_ip : valid_ips_array) {
                      if (ipAddr.equals(valid_ip.trim())) {
                          isPresent = true;
                      }
                    }
                    if (isPresent) {
                       result.setStatus(IResult.SUCCEEDED);
                    } else {
                       result.setStatus(IResult.FAILED);
                       result.setFault(new WSMException(WSMException.FAULT_FAILED
_CHECK));
                    }
               } else {
                result.setStatus(IResult.SUCCEEDED);
               }
               return result;
          }
        } catch (Exception e) {
            throw new WSMException(WSMException.FAULT_FAILED_CHECK, e);
        }
    }
 
    public oracle.wsm.common.sdk.IResult
 postExecute(oracle.wsm.common.sdk.IContext p1) {
        IResult result = new Result();
        result.setStatus(IResult.SUCCEEDED);
        return result;
    }
}

サンプル・ポリシー・ファイル

例3-2は、サンプル・ポリシー・ファイルを示しています。

例3-2 サンプル・ポリシー・ファイル

<?xml version = '1.0' encoding = 'UTF-8'?>
<wsp:Policy xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy"
 xmlns:orasp="http://schemas.oracle.com/ws/2006/01/securitypolicy"
orawsp:status="enabled"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-uti
lity-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orawsp:category="security"
 orawsp:attachTo="binding.server" wsu:Id="ip_assertion_policy"
xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
 xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
wsp:Name="oracle/ip_assertion_policy">
           <orasp:ipAssertion orawsp:Silent="true" orawsp:Enforced="true"
 orawsp:name="WSSecurity IpAsertion validator"
 orawsp:category="security/authentication">
               <orawsp:bindings>
                    <orawsp:Config orawsp:name="ipassertion"
 orawsp:configType="declarative">
                         <orawsp:PropertySet orawsp:name="valid_ips">
                               <orawsp:Property orawsp:name="valid_ips"
 orawsp:type="string" orawsp:contentType="constant">
                                    <orawsp:Value>140.87.6.143,10.178.93.107</orawsp:Value>
                                </orawsp:Property>
                         </orawsp:PropertySet>
                     </orawsp:Config>
               </orawsp:bindings>
            </orasp:ipAssertion>
</wsp:Policy>

サンプルのpolicy-config.xml

例3-3は、policy-config.xmlファイルを使用して、カスタム・アサーション・エグゼキュータを指定する方法を示しています。第2.2.3項「手順3: カスタム・アサーション・エグゼキュータの指定」で説明されているように、カスタム・ポリシーを使用して、カスタム・ポリシー・エグゼキュータを指定することもできます。

例3-3 サンプルのpolicy-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<policy-config>
    <policy-model-config>
      <entry>
        <key namespace="http://schemas.oracle.com/ws/2006/01/securitypolicy"
 element-name="ipAssertion"/>
        <executor-classname>sampleassertion.IpAssertionExecutor</executor-classname>
      </entry>
    </policy-model-config>
</policy-config>

サンプルのWebサービス

例3-4は、サンプルのWebサービスを示しています。第2.2.7項「手順7: Webサービスへのカスタム・ポリシーの添付」で説明されているように、カスタム・アサーションをWebサービスに添付できます。

例3-4 サンプルのWebサービス

package project1; 
import javax.jws.WebService;
import weblogic.wsee.jws.jaxws.owsm.SecurityPolicies;
@WebService
@SecurityPolicy(uri="policy:oracle/ip_assertion_policy")
public class Class1 {
    public Class1() {
        super();
    }
 
    public String echo1() {
        return "one";
    }
}

サンプルのJSEクライアント

例3-5は、例3-4のWebサービスから生成されたJSEクライアントのサンプルです。

例3-5 サンプルのJSEクライアント

package project1;
import javax.xml.ws.WebServiceRef;
 
public class Class1PortClient
{
  @WebServiceRef
  private static Class1Service class1Service;
  public static void main(String [] args)
  {
    class1Service = new Class1Service();
    Class1 port = class1Service.getClass1Port();
    // Add your code to call the desired methods.
 
    System.out.println(port.echo1());
  }
}

3.2.2 このサンプルの実行

IP検証のカスタム・アサーションのサンプルを使用するには、次の手順を実行します。

  1. 第3.2.1項「コード・サンプル」で説明されているように、サンプル・コードを使用して、カスタム・アサーションとカスタム・アサーション・エグゼキュータを作成します。これらのサンプルは次の主な機能を示しています。

  2. 第2.2.4項「手順4: JARファイルの作成」で説明されているように、JARファイルを作成します。

  3. 第2.2.5項「手順5: カスタム・ポリシーのポリシー・ストアへの追加」で説明されているように、カスタム・ポリシーをポリシー・ストアに追加します。

  4. 第2.2.6項「手順6: カスタム・アサーションのデプロイ」で説明されているように、クラスパスを更新します。

  5. 第2.2.7項「手順7: Webサービスへのカスタム・ポリシーの添付」で説明されているメソッドのいずれかに従って、カスタム・ポリシーをWebサービスに添付します。

  6. 例3-5に示すように、JSEクライアントを作成することで、Webサービスをテストすることもできます。

3.3 暗号化と復号化のカスタム・アサーションのサンプル

このサンプルでは、カスタム・アサーションのセットを使用して、インバウンド・メッセージからデータを暗号化し、コンソール、監査証跡またはログから読み取られないようにします。暗号化されたデータは、データのアクセスを必要とするダウンストリーム・サービスのアウトバウンド・メッセージのために復号化されます。

次の各項では、カスタム・アサーションをコード化する方法を示すサンプルを提示し、サンプルを詳細に説明します。

3.3.1 コード・サンプル

この項では、カスタム・アサーションを作成および実装する次のサンプル・コードを示します。

サンプル・カスタム・アサーション・エグゼキュータ

例3-6は、データの暗号化と復号化に使用するサンプルのカスタム・アサーション・エグゼキュータを示しています。実装の詳細は、第3.3.2項「サンプルの実行」を参照してください。

例3-6 サンプルのカスタム・アサーション・エグゼキュータ

package owsm.custom.soa;
 
import java.util.HashMap;
import java.util.Iterator;
 
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
 
import oracle.wsm.common.sdk.IContext;
import oracle.wsm.policy.model.IAssertion;
import oracle.wsm.policyengine.IExecutionContext;
import oracle.wsm.policyengine.impl.AssertionExecutor;
 
import org.w3c.dom.Element;
import org.w3c.dom.Node;
 
/**
 * A base class for OWSM custom assertions that specific classes can extend. It
 * contains common code and variables used accross all custom assertions.
 * 
 * All custom assertions must extend the AssertionExecutor class.
 */
public abstract class CustomAssertion
  extends AssertionExecutor
{
 
 
  protected final static String PROP_DEBUG = "debugFlag";
  
  protected final static String DEBUG_START =
 "===========================================================>>>";
  protected final static String DEBUG_END =
 "<<<===========================================================";
 
  protected IAssertion mAssertion = null;
  protected IExecutionContext mEcontext = null;
  protected oracle.wsm.common.sdk.IContext mIcontext = null;
  
  /**
   * A tag or text to display when printing debug information to identify the
   * content.
   */
  protected String mTag;
 
  /**
   * Constructor
   */
  public CustomAssertion(String tag)
  {
    super();
    mTag = tag;
  } // CustomAssertion()
 
  /**
   * Implemented from parent class
   */
  public void init(IAssertion iAssertion,
                      IExecutionContext iExecutionContext,
                      IContext iContext)
  {
    mAssertion = iAssertion;
    mEcontext = iExecutionContext;
    mIcontext = iContext;
    //IAssertionBindings bindings = ((SimpleAssertion)

 (mAssertion)).getBindings();
  } // init()
  /**
   * Implemented from parent class
   */
  public void destroy()
  {
    // Nothing to do.
  } // destroy()
  
  /**
   * A utility method for extracting the node specified by <code>xpathStr</code>
   * (with namespaces defined by <code>namespaces</code>) from  
 *<code>payload</code>
   * 
   * This method will print an stack trace if their is an exception. If you want
 *to
   * return the exception instead then modify the method appropriately.
   * 
   * @param payload the payload
   * @param namespaces the namespaces referenced by <code>xpathStr</code>
   * @param xpathStr an XPath query defining how to extract a node from
 *<code>payload</code>
   * @return
   */
  public static Node getDataNode(Element payload, final HashMap<String, String>

 namespaces, String xpathStr)
  {
    Node node = null;
    
    try
    {
      // Create a namespace context based on the namespaces passed in.
      //
      NamespaceContext ctx = new NamespaceContext()
      {
        public String getNamespaceURI(String prefix)
        {
          return namespaces.get(prefix);
        }
        // Dummy implementation - not used
        public Iterator getPrefixes(String val)
        {
          return null;
        }
        // Dummy implemenation - not used
        public String getPrefix(String uri)
        {
          return null;
        }
      };
      XPathFactory xpathFact = XPathFactory.newInstance();
      XPath xpath = xpathFact.newXPath();
      xpath.setNamespaceContext(ctx);
            node = (Node)xpath.evaluate(xpathStr, payload, XPathConstants.NODE);
    }
    catch (XPathExpressionException ex)
    {
      ex.printStackTrace();
      return null;
    }
    
    return node;
  } // getDataNode()
  
} 

サンプルのインバウンド暗号化クラス

例3-7は、インバウンド・メッセージの要素を暗号化するためのサンプル・カスタム・アサーション・エグゼキュータを示しています。

例3-7 サンプルのインバウンド暗号化クラス

package owsm.custom.soa;
 
import java.util.HashMap;
 
import javax.xml.soap.SOAPBody;
 
import oracle.wsm.common.sdk.IContext;
import oracle.wsm.common.sdk.IMessageContext;
import oracle.wsm.common.sdk.IResult;
import oracle.wsm.common.sdk.Result;
import oracle.wsm.common.sdk.SOAPBindingMessageContext;
import oracle.wsm.common.sdk.WSMException;
import oracle.wsm.policy.model.IAssertionBindings;
import oracle.wsm.policy.model.IConfig;
import oracle.wsm.policy.model.IProperty;
import oracle.wsm.policy.model.IPropertySet;
import oracle.wsm.policy.model.impl.SimpleAssertion;
 
import oracle.xml.parser.v2.XMLElement;
 
import org.w3c.dom.Node;
 
 
/**
 * A custom assertion class for encrypting an element of an inbound message.
 */
public class InboundEncryptor
  extends CustomAssertion
{
  /**
   * Constructor
   */
  public InboundEncryptor()
  {
    super("[InboundEncryptor] ");
  } // InboundEncryptor()
 

 
  /**
   * Process an inbound message for the given invocation context
   *
   * @param iContext the invocation context for a specific message
   * @return the result of any actions taken. It can return a success message or
   *         a fault with an exception message
   */
  public IResult execute(IContext iContext)
  {
    // Create the result that's going be populate with success or failure
    // depending on what happens.
    //
    IResult result = new Result();
    
    // Specify whether we are in debug mode or not. If true then debug statements
    // will be printed to the log file.
    // This can be set to true in the OWSM policy assertion.
    //
    boolean debug = false;
 
    try
    {
      // Get the property set which contains properties defined in the OWSM
      // policy assertion.
      //
      IAssertionBindings bindings = ((SimpleAssertion)
 (mAssertion)).getBindings();
      IConfig config = bindings.getConfigs().get(0);
      IPropertySet propertyset = config.getPropertySets().get(0);
 
      // Now that we have the property set, let's check it for the specific
      // properties we care about.
      //
      
      // Check for the debug flag property.
      //
      IProperty debugProp = propertyset.getPropertyByName(PROP_DEBUG);
      if (debugProp != null)
      {
        String debugStr = debugProp.getValue();
        debug = Boolean.valueOf(debugStr).booleanValue();
      }
      if (debug)
      {
        System.out.println(mTag+DEBUG_START);
        System.out.println(mTag+this.getClass().getSimpleName()+".execute()
 Starting...");
        System.out.println(mTag+"In debug mode");
      }
      
      // Check for the stage. We only care about the request stage for this
      // implementation.
      //
      IMessageContext.STAGE stage = ((IMessageContext) iContext).getStage();
      if (debug) System.out.println(mTag+"stage="+stage);
      if (stage != IMessageContext.STAGE.request)
      {
        result.setStatus(IResult.SUCCEEDED);
        if (debug)
        {
          System.out.println(mTag+"Nothing to process in this stage. Returning");
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
      // Get the encryption key, which is a property on the assertion.
      //
      String key = propertyset.getPropertyByName("encryption_key").getValue();
      if (debug) System.out.println(mTag+"key=[" + key + "]");
      if (key == null || key.trim().length() == 0)
      {
        result.setStatus(IResult.FAILED);
        result.setFault(new WSMException("Invalid key"));
        if (debug)
        {
          System.out.println(mTag+"Invalid key");
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
      // As as point of interest, you can get the service URL. This could be used
      // by this class to know which service this message is bound for, and
 //therefore
      // which XPath expression to use.
      // In this example no such logic is needed as we only have one servcie
      // to worry about.
      //
      if (debug)
      {
        String serviceURL = ((IMessageContext) iContext).getServiceURL();
        System.out.println(mTag+"serviceURL=[" + serviceURL+"]");
      }
      // Get the message.
      //
      SOAPBindingMessageContext soapbindingmessagecontext =
 (SOAPBindingMessageContext) iContext;
      javax.xml.soap.SOAPMessage soapMessage =
 soapbindingmessagecontext.getRequestMessage();
      SOAPBody soapElem = soapMessage.getSOAPBody();
      if (debug)
      {
        System.out.println(mTag+"----- Start ORIGINAL inbound message -----");
        ((XMLElement) soapElem).print(System.out);
        System.out.println(mTag+"-----  End ORIGINAL inbound message  -----");
      }
      // Create the XPath to reference the element which is to be encrypted.
      //
      String xpathStr =
 "/soap:Envelope/soap:Body/ns1:process/ns1:order/ns1:ccNum";
      // Build up a namespace list for any namespaces referenced by the
      // XPath expression. This will be the basis for a namespace context
      // created later.
      //
      final HashMap<String, String> namespaces = new HashMap<String, String>();
      namespaces.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
      namespaces.put("ns1", "http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionComposite/ProcessCustomer");
     
      // Extract the node that should be encrypted.
      //
      Node inputNode = getDataNode(soapElem, namespaces, xpathStr);
      if (inputNode == null)
      {
        // Something went wrong, but getDataNode() would've printed out a
 //stacktrace
        // so print out a debug statement and exit.
        //
        result.setStatus(IResult.FAILED);
        result.setFault(new WSMException("Cannot find node with XPath expression:
 "+xpathStr));
        if (debug)
        {
          System.out.println(mTag+"Cannot find node with XPath expression:
 "+xpathStr);
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
  
      // Extract the string value of the element to be encrypted.
      //
      String inputValue = inputNode.getTextContent();
  
      // Get an instance of EncDec and perform the actual encryption.
      //
      EncDec ed = EncDec.getInstance();
      String encryptedInput = ed.encryptStrToStr(inputValue, key);
      if (debug) System.out.println(mTag+"result of encryption=[" + encryptedInput
 + "]");
      // Replace the value of the node with the encrypted value.
      //
      try
      {
        inputNode.setTextContent(encryptedInput);
      }
      catch (Exception ex)
      {
        ex.printStackTrace();
      }
      if (debug)
      {
        System.out.println(mTag+"----- Start MODIFIED inbound message -----");
        ((XMLElement) soapElem).print(System.out);
        System.out.println(mTag+"-----  End MODIFIED inbound message  -----");
      }
      // Set a happy result.
      //
      result.setStatus(IResult.SUCCEEDED);
    }
    catch (Exception e)
    {
      // This is a general or catchall handler.
      //
      result.setStatus(IResult.FAILED);
      result.setFault(new WSMException(WSMException.FAULTCODE_QNAME_FAILED_CHECK,
 e));
      if (debug) System.out.println(this.getClass().getName()+": ERROR: Got an
 exception somewhere...");
    }
    
    if (debug) System.out.println(mTag+DEBUG_END);
    return result;
    
  } // execute()
  
} // InboundEncryptor

サンプルのアウトバウンド復号化クラス

例3-8は、アウトバウンド・メッセージの要素を復号化するためのサンプル・カスタム・アサーション・エグゼキュータを示しています。

例3-8 サンプルのアウトバウンド復号化クラス

package owsm.custom.soa;
 
import java.util.HashMap;
 
import javax.xml.soap.SOAPBody;
 
import oracle.wsm.common.sdk.IContext;
import oracle.wsm.common.sdk.IMessageContext;
import oracle.wsm.common.sdk.IResult;
import oracle.wsm.common.sdk.Result;
import oracle.wsm.common.sdk.SOAPBindingMessageContext;
import oracle.wsm.common.sdk.WSMException;
import oracle.wsm.policy.model.IAssertionBindings;
import oracle.wsm.policy.model.IConfig;
import oracle.wsm.policy.model.IProperty;
import oracle.wsm.policy.model.IPropertySet;
import oracle.wsm.policy.model.impl.SimpleAssertion;
 
import oracle.xml.parser.v2.XMLElement;
 
import org.w3c.dom.Node;
 
 
/**
 * A custom assertion class for decrypting an element of an outbound message.
 */
public class OutboundDecryptor
  extends CustomAssertion
{
 
  /**
   * Constructor
   */
  public OutboundDecryptor()
  {
    super("[OutboundDecryptor] ");
  } // OutboundDecryptor()
 
  //////////////////////////////////////////////////////////////////////////////
 
  /**
   * Process an outbound message for the given invocation context
   *
   * @param iContext the invocation context for a specific message
   * @return the result of any actions taken. It can return a success message or
   *         a fault with an exception message
   */
  public IResult execute(IContext iContext)
  {
    // Create the result that's going be populate with success or failure
    // depending on what happens.
    //
    IResult result = new Result();
 
    // Specify whether we are in debug mode or not. If true then debug statements
    // will be printed to the log file.
    // This can be set to true in the OWSM policy assertion.
    //
    boolean debug = false;
 
    try
    {
      // Get the property set which contains properties defined in the OWSM
      // policy assertion.
      //
      IAssertionBindings bindings = ((SimpleAssertion)
 (mAssertion)).getBindings();
      IConfig config = bindings.getConfigs().get(0);
      IPropertySet propertyset = config.getPropertySets().get(0);
      
      // Now that we have the property set, let's check it for the specific
      // properties we care about.
      //
      
      // Check for the debug flag property.
      //
      IProperty debugProp = propertyset.getPropertyByName(PROP_DEBUG);
      if (debugProp != null)
      {
        String debugStr = debugProp.getValue();
        debug = Boolean.valueOf(debugStr).booleanValue();
      }
      if (debug)
      {
        System.out.println(mTag+DEBUG_START);
        System.out.println(mTag+this.getClass().getSimpleName()+".execute()
 Starting...");
        System.out.println(mTag+"In debug mode");
      }
 
      // Check for the stage. We only care about the request stage for this
      // implementation.
      //
      IMessageContext.STAGE stage = ((IMessageContext) iContext).getStage();
      if (debug) System.out.println(mTag+"stage="+stage);
      if (stage != IMessageContext.STAGE.request)
      {
        result.setStatus(IResult.SUCCEEDED);
        if (debug)
        {
          System.out.println(mTag+"Nothing to process in this stage. Returning");
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
      // Get the encryption key, which is a property on the assertion.
      //
      String key = propertyset.getPropertyByName("decryption_key").getValue();
      if (debug) System.out.println(mTag+"key=[" + key + "]");
      if (key == null || key.trim().length() == 0)
      {
        result.setStatus(IResult.FAILED);
        result.setFault(new WSMException("Invalid key"));
        if (debug)
        {
          System.out.println(mTag+"Invalid key");
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
      String serviceURL = ((IMessageContext) iContext).getServiceURL();
      if (debug) System.out.println(mTag+"serviceURL=[" + serviceURL+"]");
      // Get the message.
      //
      SOAPBindingMessageContext soapbindingmessagecontext =

 (SOAPBindingMessageContext) iContext;
      javax.xml.soap.SOAPMessage soapMessage =
 soapbindingmessagecontext.getRequestMessage();
      SOAPBody soapElem = soapMessage.getSOAPBody();
                                                    
      // As as point of interest, you can get the service URL. This could be used
      // by this class to know which service this message is bound for, and
 //therefore
      // which XPath expression to use.
      // In this example no such logic is needed as we only have one servcie
      // to worry about.
      //
      if (debug)
      {
        System.out.println(mTag+"----- Start ORIGINAL inbound message -----");
        ((XMLElement) soapElem).print(System.out);
        System.out.println(mTag+"-----  End ORIGINAL inbound message  -----");
      }
      // Create the XPath to reference the element which is to be encrypted.
      //
      String xpathStr = "/soap:Envelope/soap:Body/ns1:process/ns1:ccNum";
      
      // Build up a namespace list for any namespaces referenced by the
      // XPath expression. This will be the basis for a namespace context
      // created later.
      //
      final HashMap<String, String> namespaces = new HashMap<String, String>();
      namespaces.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
      namespaces.put("ns1", "http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel");
    
      // Extract the node that should be encrypted.
      //
      Node inputNode = getDataNode(soapElem, namespaces, xpathStr);
      if (inputNode == null)
      {
        // Something went wrong, but getDataNode() would've printed out a
 //stacktrace
        // so print out a debug statement and exit.
        //
        result.setStatus(IResult.FAILED);
        result.setFault(new WSMException("Cannot find node with XPath expression:
 "+xpathStr));
        if (debug)
        {
          System.out.println(mTag+"Cannot find node with XPath expression:
 "+xpathStr);
          System.out.println(mTag+DEBUG_END);
        }
        return result;
      }
    
      // Extract the string value of the element to be encrypted.
      //
      String inputValue = inputNode.getTextContent();
    
      // Get an instance of EncDec and perform the actual encryption.
      //
      EncDec ed = EncDec.getInstance();
      String decryptedInput = ed.decryptStrToStr(inputValue, key);
      if (debug) System.out.println(mTag+"result of decryption=[" + decryptedInput
 + "]");
      // Replace the value of the node with the encrypted value.
      //
      try
      {
        inputNode.setTextContent(decryptedInput);
      }
      catch (Exception ex)
      {
        ex.printStackTrace();
      }
      if (debug)
      {
        System.out.println(mTag+"----- Start MODIFIED inbound message -----");
        ((XMLElement) soapElem).print(System.out);
        System.out.println(mTag+"-----  End MODIFIED inbound message  -----");
      }
      // Set a happy result.
      //
      result.setStatus(IResult.SUCCEEDED);
    }
    catch (Exception e)
    {
      // This is a general or catchall handler.
      //
      result.setStatus(IResult.FAILED);
      result.setFault(new WSMException(WSMException.FAULTCODE_QNAME_FAILED_CHECK,
 e));
      if (debug) System.out.println(this.getClass().getName()+": ERROR: Got an
 exception somewhere...");
    }
    
    if (debug) System.out.println(mTag+DEBUG_END);
    return result;
    
  } // execute()
  
} // OutboundDecryptor

暗号化のためのサンプル・ポリシー・ファイル

例3-9は、暗号化のためのサンプルのカスタム・アサーション・エグゼキュータを示しています。

例3-9 暗号化のためのサンプル・ポリシー・ファイル

<orasp:Assertion xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
                          orawsp:Id="soa_encryption_template"
                          orawsp:attachTo="generic" orawsp:category="security"
                          orawsp:description="Custom Encryption of payload"
                          orawsp:displayName="Custom Encryption"
                          orawsp:name="custom/soa_encryption"
                          xmlns:custom="http://schemas.oracle.com/ws/soa/custom">
  <custom:custom-executor orawsp:Enforced="true" orawsp:Silent="false"
                   orawsp:category="security/custom"
                   orawsp:name="WSSecurity_Custom_Assertion">
    <orawsp:bindings>
      <orawsp:Implementation>owsm.custom.soa.InboundEncryptor</orawsp:Implementation>
      <orawsp:Config orawsp:configType="declarative" orawsp:name="encrypt_soa">
        <orawsp:PropertySet orawsp:name="encrypt">
          <orawsp:Property orawsp:contentType="constant"
                           orawsp:name="encryption_key" orawsp:type="string">
            <orawsp:Value>MySecretKey</orawsp:Value>
          </orawsp:Property>
          <orawsp:Property orawsp:contentType="constant"
                           orawsp:name="debugFlag" orawsp:type="string">
            <orawsp:Value>true</orawsp:Value>
          </orawsp:Property>
        </orawsp:PropertySet>
      </orawsp:Config>
    </orawsp:bindings>
  </custom:custom-executor>
</orasp:Assertion>

復号化のためのサンプル・ポリシー・ファイル

例3-10は、復号化のためのサンプルのカスタム・アサーションを示しています。

例3-10 復号化のためのサンプル・ポリシー・ファイル

<orasp:Assertion xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
                          orawsp:Id="soa_decryption_template"
                          orawsp:attachTo="binding.client"
 orawsp:category="security"
                          orawsp:description="Custom Decryption of payload"
                          orawsp:displayName="Custom Decryption"
                          orawsp:name="custom/soa_decryption"
                          xmlns:custom="http://schemas.oracle.com/ws/soa/custom">
  <custom:custom-executor orawsp:Enforced="true" orawsp:Silent="false"
                   orawsp:category="security/custom"
                   orawsp:name="WSSecurity Custom Assertion">
    <orawsp:bindings>
      <orawsp:Implementation>owsm.custom.soa.OutboundDecryptor</orawsp:Implementation>
      <orawsp:Config orawsp:configType="declarative" orawsp:name="encrypt_soa">
        <orawsp:PropertySet orawsp:name="decrypt">
          <orawsp:Property orawsp:contentType="constant"
                           orawsp:name="decryption_key" orawsp:type="string">
            <orawsp:Value>MySecretKey</orawsp:Value>
          </orawsp:Property>
          <orawsp:Property orawsp:contentType="constant"
                           orawsp:name="debugFlag" orawsp:type="string">
            <orawsp:Value>true</orawsp:Value>
          </orawsp:Property>
        </orawsp:PropertySet>
      </orawsp:Config>
    </orawsp:bindings>
  </custom:custom-executor>
</orasp:Assertion>

暗号化されたメッセージを受信するためのサンプル・コンポジット

次のサンプルは、暗号化された値を受信したことを示すために使用されるBPELプロセスを含むコンポジット・アプリケーションです。

例3-11 サンプル・コンポジット

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 1.0 at [5/10/10 9:33 AM]. -->
<composite name="CustomEncryptionComposite"
           revision="1.0"
           label="2010-05-10_09-33-01_807"
           mode="active"
           state="on"
           xmlns="http://xmlns.oracle.com/sca/1.0"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
           xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
           xmlns:ui="http://xmlns.oracle.com/soa/designer/">
  <import namespace="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionComposite/ProcessCustomer"
          location="ProcessCustomer.wsdl" importType="wsdl"/>
  <import namespace="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel"
          location="ExternalServiceBpel.wsdl" importType="wsdl"/>
  <service name="processcustomer_client_ep"
           ui:wsdlLocation="ProcessCustomer.wsdl">
    <interface.wsdl interface="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionComposite/ProcessCustomer#wsdl.interface(ProcessCustomer)"/>
    <binding.ws port="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionComposite/ProcessCustomer#wsdl.endpoint(processcustomer
_client_ep/ProcessCustomer_pt)">
      <wsp:PolicyReference URI="SOA/CustomEncryption" orawsp:category="security"
                           orawsp:status="enabled"/>
    </binding.ws>
  </service>
  <component name="ProcessCustomer">
    <implementation.bpel src="ProcessCustomer.bpel"/>
  </component>
  <reference name="ExternalSvc" ui:wsdlLocation="ExternalServiceBpel.wsdl">
    <interface.wsdl interface="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel#wsdl.interface(ExternalSe
rviceBpel)"/>
    <binding.ws port="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel#wsdl.endpoint(externalser
vicebpel_client_ep/ExternalServiceBpel_pt)"
                location="externalservicebpel_client_ep.wsdl"
                soapVersion="1.1">
      <wsp:PolicyReference URI="SOA/CustomDecryption" orawsp:category="security"
                           orawsp:status="enabled"/>
      <property name="weblogic.wsee.wsat.transaction.flowOption"
                type="xs:string" many="false">WSDLDriven</property>
    </binding.ws>
  </reference>
  <wire>
    <source.uri>processcustomer_client_ep</source.uri>
    <target.uri>ProcessCustomer/processcustomer_client</target.uri>
  </wire>
  <wire>
    <source.uri>ProcessCustomer/ExternalSvc</source.uri>
    <target.uri>ExternalSvc</target.uri>
  </wire>
</composite>

サンプルの外部サービス・コンポジット

次のサンプルは、呼び出されている外部サービスを示し、復号化された値を受信したことを示すために使用されるコンポジット・アプリケーションです。

例3-12 サンプルの外部サービス・コンポジット

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 1.0 at [5/10/10 9:41 AM]. -->
<composite name="CustomEncryptionExternalService"
           revision="1.0"
           label="2010-05-10_09-41-00_810"
           mode="active"
           state="on"
           xmlns="http://xmlns.oracle.com/sca/1.0"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
           xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
           xmlns:ui="http://xmlns.oracle.com/soa/designer/">
  <import namespace="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel"
          location="ExternalServiceBpel.wsdl" importType="wsdl"/>
  <service name="externalservicebpel_client_ep"
           ui:wsdlLocation="ExternalServiceBpel.wsdl">
    <interface.wsdl interface="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel#wsdl.interface(ExternalSe
rviceBpel)"/>
    <binding.ws port="http://xmlns.oracle.com/CustomEncryption
_jws/CustomEncryptionExternalService/ExternalServiceBpel#wsdl.endpoint(externalser
vicebpel_client_ep/ExternalServiceBpel_pt)"/>
  </service>
  <component name="ExternalServiceBpel">
    <implementation.bpel src="ExternalServiceBpel.bpel"/>
  </component>
  <wire>
    <source.uri>externalservicebpel_client_ep</source.uri>
    <target.uri>ExternalServiceBpel/externalservicebpel_client</target.uri>
  </wire>
</composite>

3.3.2 サンプルの実行

暗号化と復号化のサンプルを使用するには、次の手順を実行します。

  1. 第3.3.1項「コード・サンプル」で説明されているように、サンプル・コードを使用して、ポリシー・ファイルとカスタム・アサーション・エグゼキュータを作成します。これらのサンプルは次の主な機能を示しています。

    • 暗号化カスタム・アサーションの暗号化プロパティ・セットのプロパティencryption_keyとdebugFlagを指定します。

              <orawsp:PropertySet orawsp:name="encrypt">
                <orawsp:Property orawsp:contentType="constant"
                                 orawsp:name="encryption_key"
      orawsp:type="string">
                  <orawsp:Value>MySecretKey</orawsp:Value>
                </orawsp:Property>
                <orawsp:Property orawsp:contentType="constant"
                                 orawsp:name="debugFlag" orawsp:type="string">
                  <orawsp:Value>true</orawsp:Value>
                </orawsp:Property>
              </orawsp:PropertySet>
      

      詳細は、第4.1項「カスタム・アサーションへのパラメータの入力」を参照してください。

    • 復号化カスタム・アサーションの復号化プロパティ・セットのプロパティdecryption_keyとdebugFlagを指定します。

              <orawsp:PropertySet orawsp:name="decrypt">
                <orawsp:Property orawsp:contentType="constant"
                                 orawsp:name="decryption_key"
       orawsp:type="string">
                  <orawsp:Value>MySecretKey</orawsp:Value>
                </orawsp:Property>
                <orawsp:Property orawsp:contentType="constant"
                                 orawsp:name="debugFlag" orawsp:type="string">
                  <orawsp:Value>true</orawsp:Value>
                </orawsp:Property>
              </orawsp:PropertySet>
      

      詳細は、第4.1項「カスタム・アサーションへのパラメータの入力」を参照してください。

    • カスタム・アサーション・クラスから、定義済のネームスペースを含むXPath式で指定されたノードを抽出します。

      NamespaceContext ctx = new NamespaceContext()
            {
              public String getNamespaceURI(String prefix)
              {
                return namespaces.get(prefix);
              }
              // Dummy implementation - not used
              public Iterator getPrefixes(String val)
              {
                return null;
              }
              // Dummy implemenation - not used
              public String getPrefix(String uri)
              {
                return null;
              }
            };
            XPathFactory xpathFact = XPathFactory.newInstance();
            XPath xpath = xpathFact.newXPath();
            xpath.setNamespaceContext(ctx);
            
            node = (Node)xpath.evaluate(xpathStr, payload, XPathConstants.NODE);
          }
      
      

      詳細は、第4.4項「XPathによるメッセージのパーツへのアクセス」を参照してください。

  2. 第2.2.4項「手順4: JARファイルの作成」で説明されているように、JARファイルを作成します。

  3. 第2.2.5項「手順5: カスタム・ポリシーのポリシー・ストアへの追加」で説明されているように、カスタム・ポリシーをポリシー・ストアに追加します。

  4. 第2.2.6項「手順6: カスタム・アサーションのデプロイ」で説明されているように、クラスパスを更新します。

  5. 第2.2.7項「手順7: Webサービスへのカスタム・ポリシーの添付」で説明されているメソッドのいずれかに従って、カスタム・ポリシーをWebサービスに添付します。

3.4 認証のカスタム・アサーションのサンプル

認証カスタム・アサーションのサンプルは、WebLogic認証プロバイダを使用してユーザーを認証するために使用されます。資格証明(ユーザー名とパスワード)は着信メッセージから読み取られ、カスタム・ログイン・モジュールを使用して、WebLogic認証プロバイダに対して認証されます。

次の各項では、カスタム・アサーションをコード化する方法を示すサンプルを提示し、サンプルを詳細に説明します。

3.4.1 コード・サンプル

この項では、カスタム・アサーションを作成および実装する次のサンプル・コードを示します。

サンプル・カスタム・アサーション・エグゼキュータ

例3-13は、カスタム・ログイン・モジュールを起動して認証を実行するサンプル・エグゼキュータを示しています。

例3-13 サンプルのカスタム・アサーション・エグゼキュータ

package sampleAssertion;
/**
 * <Description>
 * <p>
 * CustomAuthExecutor class. This class is invoked for custom_auth_policy
 * This class expects that wss_username_token_client_policy is attached to the 
* calling client
 * This class fetches credentials from incoming SOAP message and performs
 * authentication against a configured login module as specified by the Login 
* Config file.
 * </p>
 * </Description>
 * 
 */
import java.util.Iterator;
 
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
 
import oracle.wsm.common.sdk.IContext;
import oracle.wsm.common.sdk.IMessageContext;
import oracle.wsm.common.sdk.IResult;
import oracle.wsm.common.sdk.Result;
import oracle.wsm.common.sdk.SOAPBindingMessageContext;
import oracle.wsm.common.sdk.WSMException;
import oracle.wsm.policy.model.IAssertion;
import oracle.wsm.policy.model.ISimpleOracleAssertion;
import oracle.wsm.policyengine.impl.AssertionExecutor;
 
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
public class CustomAuthExecutor extends AssertionExecutor {
 
    public void init(IAssertion assertion,
        oracle.wsm.policyengine.IExecutionContext econtext,
        oracle.wsm.common.sdk.IContext context) {
        this.assertion = assertion;
        this.econtext = econtext;
    }
 
    public oracle.wsm.policyengine.IExecutionContext getExecutionContext() {
        return this.econtext;
    }
 
    public boolean isAssertionEnabled() {
        return ((ISimpleOracleAssertion) this.assertion).isEnforced();
    }
 
    public String getAssertionName() {
        return this.assertion.getQName().toString();
    }
 
 
    /**
     * <p>
     * This method is invoked for each request/response.
     * This method retrieves credentials from incoming soap message and 
     * authenticates 
     * them against a configured login module
     * </p>
     * @param context
     * @return IResult
     * @exception WSMException
     */
    @Override
    public IResult execute(IContext context) throws WSMException {
        oracle.wsm.common.sdk.IMessageContext.STAGE stage = ((oracle.wsm.common.sdk.IMessageContext) context)
            .getStage();
        IResult result = new Result();
 
        if (stage == IMessageContext.STAGE.request) {
            try {
                SOAPBindingMessageContext soapMsgCtxt= (SOAPBindingMessageContext)
                context;
                //Intercepts the incoming SOAP message
                SOAPMessage soapMessage = soapMsgCtxt.getRequestMessage();
                
                MyCallbackHandler callbackhandler = new MyCallbackHandler();
                
                //initialize CallbackHandler instance which is passed to 
                //LoginModule implementation
                initializeCallbackHandler(callbackhandler, soapMessage);
                
                
               //In order to authenticate a user, you first need a
               //javax.security.auth.login.LoginContext. 
               /**
 
               * Following parameters are passed to LoginContext
               * 1. name - LoginContext uses the name as the index into the JAAS
               * login configuration file to determine which LoginModules should 
               * be used. Such an entry specifies the class(es) that
               * implement the desired underlying authentication
               * technology(ies). The class(es) must implement 
               *  the LoginModule interface, which is in the
               * javax.security.auth.spi package.
               * In our case CustomLoginModule refers to
               * sampleAssertion.loginmodule.CustomLoginModule
               *
               * 2. Subject - the subject (javax.security.auth.Subject) to
               * authenticate. LoginContext passes the Subject
               * object to configured LoginModules so they may perform
               * additional authentication and update the Subject.
               *           
               * 3. CallbackHandler instance -
               * javax.security.auth.callback.CallbackHandler  object is used by
               * LoginModules to 
               * communicate with the user. LoginContext passes the
               * CallbackHandler object to configured LoginModules 
               *  so they may communicate with the user. An application
               * typically provides its own CallbackHandler implementation.
               * 
               **/
 
 
                // Obtain a LoginContext, needed for authentication. 
                // Tell it to use the LoginModule implementation 
               // specified by the entry named "CustomLoginModule" in the 
               // JAAS login configuration file and to also use the 
               // specified CallbackHandler.
                Subject subject = new Subject();
               LoginContext lc = new LoginContext("CustomLoginModule", subject,
               callbackhandler);
                
               /**Once the caller has instantiated a LoginContext, it invokes the
               * login method to authenticate a Subject
               * The LoginContext instantiates a new empty
               * javax.security.auth.Subject object (which represents the user or
               * service being
               * authenticated). 
               * The LoginContext constructs the configured LoginModule (in our
               * case CustomLoginModule) and initializes it with this new Subject
               * and
               * MyCallbackHandler.
               * The SampleLoginModule will utilize the MyCallbackHandler to
               * obtain the user name and password.
               * If authentication is successful, the CustomLoginModule
               * populates the Subject with a Principal representing the user. 
               * 
                **/
               lc.login();
                
               //authenticated Subject can be retrieved by calling the               
               // LoginContext's getSubject
                //method
                 subject = lc.getSubject();
 
 System.out.println("Authentication succeeded");
                
                //sets result to succeeded if authentication succeeds
  result.setStatus(IResult.SUCCEEDED);
  } catch (LoginException e) {
               //in case there is a failure in authentication sets result to
               // failed state and
               // throw Failed authentication exception
                result.setStatus(IResult.FAILED);
                throw new WSMException(
                    WSMException.FAULTCODE_QNAME_FAILED_AUTHENTICATION, e);
            }
        }
 
        return result;
    }
 
                   /**
                    * Retrieves credentials from incoming SOAP message and 
                    * sets them into call back handler, which is than passed to
                    * Login module
                    * class
                    * via initialize(Subject, Callbackhandler,..) method of
                    *  LoginModule 
                    * @param SOAPMessage
                    * @param callbackhandler
                    * 
                    */
    private void initializeCallbackHandler(MyCallbackHandler callbackhandler,
 SOAPMessage soapElement) {
        try {
            SOAPHeader header = soapElement.getSOAPPart().getEnvelope()
                .getHeader();
            SOAPHeaderElement hdrElem = null;
            Iterator iter = header.examineAllHeaderElements();
            
            while (iter.hasNext()) {
                hdrElem = (SOAPHeaderElement) iter.next();
                String localName = hdrElem.getLocalName();
                NodeList headerNodeList = hdrElem.getChildNodes();
 
                for (int i = 0; i < headerNodeList.getLength(); i++) {
                    Node kid = headerNodeList.item(i);
                    String kidName = kid.getLocalName();
 
                    if (kidName.equals("UsernameToken")) {
                        NodeList nodeList = kid.getChildNodes();
                        
               /**check if incoming SOAP message contains UsernameToken
                *and retrieve credentials from it
               * The user name and password are set into callbackhandler
               * which are passed to Login module
                * for authentication
                **/
                        for (int j = 0; j < nodeList.getLength(); j++) {
                            String nodeName = nodeList.item(j).getLocalName();
                            String nodeValue = nodeList.item(j).getTextContent();
 
                            if (nodeName.equals("Username")) {
                                callbackhandler.setUserName(nodeValue);
                            }
 
                            if (nodeName.equals("Password")) {
                                callbackhandler.setPassword(nodeValue);
                            }
                        }
                        
                    }
                }
            }
 
        } catch (SOAPException se) {
            System.out.println("caught SOAPException: " + se.getMessage());
        }
        
    }
 
    /**
     *Executes any task required after policy execution.
     *
     */
    @Override
    public oracle.wsm.common.sdk.IResult postExecute(
        oracle.wsm.common.sdk.IContext context) {
        IResult result = new Result();
        result.setStatus(IResult.SUCCEEDED);
        return result;
    }        @Override
    public void destroy() {
    }
   }

サンプル・ポリシー・ファイル

例3-14は、例3-13で説明されているエグゼキュータを起動するカスタム・アサーションです。これは、WebLogic認証プロバイダに対してユーザーを認証するために使用されます。

例3-14 サンプル・ポリシー・ファイル

<?xml version = '1.0'?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
 xmlns:oralgp="http://schemas.oracle.com/ws/2006/01/loggingpolicy"
 xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
orawsp:provides="{http://docs.oasis-open.org/ns/opencsa/sca/200903}authentication,
 {http://docs.oasis-open.org/ns/opencsa/sca/200903}clientAuthentication,
 {http://docs.oasis-open.org/ns/opencsa/sca/200903}clientAuthentication.message,
 {http://schemas.oracle.com/ws/2006/01/policy}token.usernamePassword"
 orawsp:status="enabled" xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-uti
lity-1.0.xsd" wsu:Id="custom_auth_policy"
orawsp:displayName="i18n:oracle.wsm.resources.policydescription.PolicyDescription
Bundle_oracle/custom_auth_policy_PolyDispNameKey"
 xmlns:orasp="http://schemas.oracle.com/ws/2006/01/securitypolicy"
orawsp:description="i18n:oracle.wsm.resources.policydescription.PolicyDescription
Bundle_oracle/custom_auth_policy_PolyDescKey" orawsp:attachTo="binding.server"
 Name="oracle/custom_auth_policy"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orawsp:category="security"
 orawsp:local-optimization="off">
   <orasp:custom-auth-assertion orawsp:Silent="false" orawsp:name="Custom auth"
 orawsp:Enforced="true" orawsp:category="security/authentication">
      <orawsp:bindings>
       <orawsp:Implementation>sampleAssertion.CustomAuthExecutor</orawsp:Implementation>
      </orawsp:bindings>
     </orasp:custom-auth-assertion>
</wsp:Policy>

サンプル認証ファイル

次のコード・サンプルは認証の実装を示しています。

  • 例3-15は、ユーザー認証を実行するために使用されるログイン・モジュールを指定するエントリが含まれているログイン構成ファイルを示しています。

  • 例3-16は、例3-15のLoginConfigファイルで指定されているCustomLoginModuleクラスのサンプルです。これは、javax.security.auth.spi.LoginModuleを実装し、WebLogic認証プロバイダに対してユーザーを認証します。

  • 例3-17は、javax.security.auth.spi.LoginModuleを実装するSimpleLoginModuleクラスのサンプルで、例示のためのものです。

  • 例3-18は、CallbackHandlerクラスのサンプルで、javax.security.auth.callback.Callbackインタフェースを実装しています。

例3-15 サンプル構成ファイル

/** Login Configuration for the Sample Application 
JAAS authentication is performed in a pluggable fashion, so Java applications can
 remain independent from 
underlying authentication technologies. Users can plugin there custom loginmodule
 implementations which 
can integrate with corresponding authentication provider.
 
The name for an entry in a login configuration file is the name that applications
 use to refer to the entry when 
they instantiate a LoginContext. The specified LoginModules (described below) are
 used to control the authentication process.
 
As part of this sample we are using CustomLoginModule and SimpleLoginModule
1. CustomLoginModule - integrates with weblogic authentication provider
2. SimpleLoginModule - simply returns
 
You can also provide implementation of javax.security.auth.login.Configuration
 interface
Refer http://download.oracle.com/javase/.../docs/api/javax/security/auth/login/Config
uration.html and 
http://download.oracle.com/javase/.../docs/guide/security/jaas/tutorials/LoginC
onfigFile.html for more details.
 
**/
 
CustomLoginModule {
   sampleAssertion.loginmodule.CustomLoginModule required debug=true;
};
 
SimpleLoginModule {
  sampleAssertion.loginmodule.SimpleLoginModule required debug=true;
};

例3-16 javax.security.auth.spi.LoginModuleの実装のサンプル

package sampleAssertion.loginmodule;
/**
 * <Description>
 * <p>
 * CustomLoginModule class implements the javax.security.auth.spi.LoginModule
 * interface. CustomLoginModule class is specified 
 * by the login configuration file i.e Login.config file.
 * This class authenticates user against weblogic authentication provider. 
 * If authentication is successful, the CustomLoginModule associate Principals and
 * Credentials with the authenticated Subject
 * 
 * Users can create there own custom login modules
 * by implementing <code>javax.security.auth.spi.LoginModule</code> interface
 * </p>
 * </Description>
 * 
 */
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
 
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
 
import weblogic.security.services.Authentication;
 
public class CustomLoginModule implements LoginModule
{
    private Subject authenticatorSubject;
    private CallbackHandler callbackHandler;
    private boolean loginSucceeded;
 
    /**
     * Initialize this LoginModule.
     *
     * <p> This method is called by the <code>LoginContext</code> to initialize 
     * the <code>LoginModule</code> with the relevant information.
     * <p>
     *
     * @param subject the - <code>javax.security.auth.Subject</code> to be
     * authenticated.
     *
     * @param callbackHandler - instance of
     * <code>javax.security.auth.callback.CallbackHandler</code>
     *   the CallbackHandler object is used by LoginModules to retrieve the
     * information set by the user
     *   e.g user name / password.
     * 
     * @param sharedState state shared with other configured LoginModules. <p>
     *
     * @param options options specified in the login Configuration for this
     *  particular LoginModule.
     *          
     **/
    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
 Map<String, ?> sharedState, Map<String, ?> options)
    {
        this.authenticatorSubject = subject;
        this.callbackHandler = callbackHandler;
    }
 
 
    @Override
    /**
     * Method to authenticate a <code>Subject</code>.
     *
     * <p> The implementation of this method authenticates
     * a <code>Subject</code> using weblogic authentication provider
     * <p>
     *
     * @exception LoginException if the authentication fails
     *
     * @return true if the authentication succeeded
     */
    public boolean login() throws LoginException
    {
        /**authenticates user against weblogic authentication provider and sets
         * loginSucceeded
         * flag to true in case of successful authentication
         */
        this.authenticatorSubject = authenticate(this.callbackHandler);
        loginSucceeded = true;
        return loginSucceeded;
    }
    
    /**
     * authenticates using weblogic authentication provider
     * @param CallbackHandler
     * @return authenticated Subject
     * @throws LoginException
     */
    private Subject authenticate(CallbackHandler cbh) throws LoginException {
        try {
            return Authentication.login(cbh);
        } catch (LoginException e) {
            throw new LoginException("Authentication Failed"+e.getMessage());
        }
    }
 
    @Override
    /**
     * Method to commit the authentication process.
     *
     * <p> This method is called if the LoginContext's
     * overall authentication succeeded
     * <p>
     *
     * @exception LoginException if the commit fails
     *
     * @return true if this method succeeded, or false if this
     *          <code>LoginModule</code> should be ignored.
     */
    public boolean commit() throws LoginException {
        if (this.authenticatorSubject != null) {
            addToSubject(this.authenticatorSubject);
            return true;
        } else {
            return false;
        }
    }
    /**
     * Method to abort the authentication process.
     *
     * <p> This method is called if the LoginContext's
     * overall authentication failed.
     * <p>
     *
     * @exception LoginException if the abort fails
     *
     * @return true if this method succeeded, or false if this
     *          <code>LoginModule</code> should be ignored.
     */
    public boolean abort() throws LoginException {
        return this.loginSucceeded && logout();
    }
    
  
    /**
     * Method which logs out a <code>Subject</code>.  
     *
     * <p>An implementation of this method might remove/destroy a Subject's
     * Principals and Credentials.
     * <p>
     *
     * @exception LoginException if the logout fails
     *
     * @return true if this method succeeded, or false if this
     *          <code>LoginModule</code> should be ignored.
     */
    public boolean logout() throws LoginException
    {
        if (this.authenticatorSubject != null) {
            removeFromSubject(this.authenticatorSubject);
        }
        this.loginSucceeded = false;
        return true;
    }
    
    /**
     * associates relevant Principals and Credentials with the Subject located in
     * the LoginModule
     * @param Subject
     */
    protected void addToSubject(final Subject sub) {
        if (sub != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
               
             authenticatorSubject.getPrincipals().addAll(sub.getPrincipals());
 authenticatorSubject.getPrivateCredentials().addAll(sub.getPrivateCredentials());
authenticatorSubject.getPublicCredentials().addAll(sub.getPublicCredentials());
                        return null;
                    }
                });
        }
    }
    
    /**
     * removes Principals and Credentials from the subject
     * @param Subject
     */
    private void removeFromSubject(final Subject sub) {
        if (sub != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
 authenticatorSubject.getPrincipals().removeAll(sub.getPrincipals());
 authenticatorSubject.getPrivateCredentials().removeAll(sub.getPrivateCredentials(


));
authenticatorSubject.getPublicCredentials().removeAll(sub.getPublicCredentials());
                        return null;
                    }
                });
        }
    }
}

例3-17 javax.security.auth.spi.LoginModuleの実装のサンプル

/**
 * <Description>
 * <p>
 * SimpleLoginModule class implements the LoginModule interface. SimpleLoginModule
 * class is specified 
 * by the login configuration file i.e Loginconfig file.
 * This class simply returns true resulting in successful authentication.
 * 
 * This class is shown for illustration purpose only, users can integrate it with
 * there custom authentication provider
 * </p>
 * </Description>
 * 
 */
package sampleAssertion.loginmodule;
 
import java.util.Map;
 
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
 
public class SimpleLoginModule implements LoginModule {
 
    @Override
    public boolean abort() throws LoginException {
        return false;
    }
 
    @Override
    public boolean commit() throws LoginException {
        return true;
    }
 
    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
        Map<String, ?> sharedState, Map<String, ?> options) {
        
    }
 
    @Override
    /**
     * This method simply returns true and results in successful authentication
     * Users can integrate it using there custom authentication provider
     */
    public boolean login() throws LoginException {
        System.out.println("Inside SimpleLoginModule");
        return true;
    }
 
    @Override
    public boolean logout() throws LoginException {
        return false;
    }
    
 
}

例3-18 サンプル・コールバック・ハンドラ

package sampleAssertion;
/**
 * <Description>
 * <p>
 * MyCallbackHandler class implements the 
 *  <code>javax.security.auth.callback.CallbackHandler </code> interface.  
 * An application implements its owm implementation of CallbackHandler.
 * An instance of CallbackHandler is passed as an argument to the LoginContext
 * instantiation. 
 * The LoginContext forwards the CallbackHandler directly to the underlying
 * LoginModules
 * so that they may interact with the application to retrieve specific
 * authentication data, 
 * such as usernames and passwords.
 * </p>
 * </Description>
 * 
 */
import java.io.IOException;
 
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
 
public class MyCallbackHandler implements CallbackHandler {
    
    private String userName = null;
    
    private String password = null;
    
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
    
    @Override
    /**
     * sets user name and password into callback
     */
    public void handle(Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {
        
        for (int i = 0; i < callbacks.length; i++) {
            Callback c = callbacks[i];
            if (c instanceof NameCallback) {
                ((NameCallback) c).setName(this.userName);
            } else if (c instanceof PasswordCallback) {
                char[] password = this.password.toCharArray();
                ((PasswordCallback) c).setPassword(password);
            } else {
                throw new UnsupportedCallbackException(callbacks[i],
                    "Unrecognized Callback");
            }
        }
        
    }
 
}

3.4.2 サンプルの実行

認証のカスタム・アサーションのサンプルを使用するには、次の手順を実行します。

  1. 第3.4.1項「コード・サンプル」で説明されているように、サンプル・コードを使用して、カスタム・アサーションとカスタム・アサーション・エグゼキュータを作成します。これらのサンプルは次の主な機能を示しています。

    • カスタム・アサーション実装クラスを定義します。

            <orawsp:bindings>    
      <orawsp:Implementation>sampleAssertion.CustomAuthExecutor
      </orawsp:Implementation>
            </orawsp:bindings>
      

      詳細は、第A.2.4項「orawsp:Implementation」を参照してください。

    • カスタム・アサーション・エグゼキュータの実行ステージを表示します。

      oracle.wsm.common.sdk.IMessageContext.STAGE stage =
       ((oracle.wsm.common.sdk.IMessageContext) context).getStage(); 
      

      詳細は、第4.3項「リクエスト、レスポンスおよびフォルト・メッセージ・オブジェクトへのアクセス」を参照してください。

    • ユーザーを認証するには、まず、javax.security.auth.login.LoginContextが必要です。LoginContextを取得します。JAAS構成ファイルのCustomLoginModuleという名前のエントリによって指定されたLoginModule実装を使用して、次のように指定されたCallbackHandlerを使用します。

      Subject subject = new Subject();
      LoginContext lc = new LoginContext("CustomLoginModule", subject,
      callbackhandler);
      

      呼出し側がLoginContextをインスタンス化すると、ログイン・メソッドを起動してサブジェクトを認証します。認証が正常終了した場合、CustomLoginModuleはユーザーを表すプリンシパルをサブジェクトに移入します。

      詳細は、http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/index.htmlを参照してください。

      initializerCallbackHandler (例3-13)を使用して、着信SOAPメッセージにUsernameTokenが含まれているかどうかを,チェックし、着信SOAPメッセージから資格証明を取得し、ログイン・モジュール・クラスにその資格証明を渡します。

    • 成功した場合、結果に成功を設定します。

      result.setStatus(IResult.SUCCEEDED);
      
    • 失敗した場合、リクエストの実行が失敗した原因となるフォルトを設定します。

      result.setStatus(IResult.FAILED);
                      throw new WSMException(
                          WSMException.FAULTCODE_QNAME_FAILED_AUTHENTICATION, e);
      

      詳細は、第4.8項「カスタム・アサーションでの例外処理」を参照してください。

  2. 第2.2.4項「手順4: JARファイルの作成」で説明されているように、JARファイルを作成します。

  3. 第2.2.5項「手順5: カスタム・ポリシーのポリシー・ストアへの追加」で説明されているように、カスタム・ポリシーをポリシー・ストアに追加します。

  4. 第2.2.6項「手順6: カスタム・アサーションのデプロイ」で説明されているように、クラスパスを更新します。

  5. 第2.2.7項「手順7: Webサービスへのカスタム・ポリシーの添付」で説明されているメソッドのいずれかに従って、カスタム・ポリシーをWebサービスに添付します。

  6. Webサービスのクライアントを作成します。このサンプル・カスタム・ポリシーは、クライアント側でwss_username_token_client_policyを使用します。wss_username_token_client_policyをクライアントに添付します。

  7. 「サンプル認証ファイル」で説明されているように、構成ファイル、および認証を実装するクラス・ファイルを作成します。構成ファイルの詳細は、http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/index.htmlのJAAS APIを参照してください。

  8. 例3-15で作成したログイン構成ファイルを指定します。次のいずれかの方法でファイルを指定できます。

    • WebLogic Serverを起動するために使用するスクリプトを編集し、javaコマンドの後に次のオプションを追加後、サーバーを再起動します。

      -Djava.security.auth.login.config==<LoginConfigファイルのパス>

    • Javaセキュリティ・プロパティ・ファイルは、<JAVA_HOME>/lib/security/java.securityという名前のファイルにあります。<JAVA_HOME>はJDKがインストールされたディレクトリを指しています。このファイルでは、"login.configuration.provider"セキュリティ・プロパティをログイン構成ファイルの完全修飾名に変更します。

  9. クライアントからリクエストを起動します。クライアントに設定されたユーザー名とパスワードは、WebLogic認証プロバイダと統合している設定済のログイン・モジュールに対して認証されます。