使用POST&amp ;; Web中心站点REST API资产创建PUT异常,响应状态401

时间:2014-01-09 11:12:07

标签: rest fatwire webcenter-sites

意图是使用java代码和Sites REST API创建资产。
首先,我无法在安装的任何地方找到REST API示例,甚至找不到11.1.1.8.0站点或JSK的源目录。 相反,我在11.1.1.6.0服务器中找到了样本。

在POSt和PUT方法中更改基本URL后我正在运行的代码:

/*
 * $Logfile:$ $Revision:$ $Date:$ Copyright © 2010 FatWire Corporation, All
 * Rights Reserved. Copyright 2010 FatWire Corporation. Title, ownership rights,
 * and intellectual property rights in and to this software remain with FatWire
 * Corporation. This software is protected by international copyright laws and
 * treaties, and may be protected by other law. Violation of copyright laws may
 * result in civil liability and criminal penalties.
 */
package com.fatwire.rest.samples.flex;

import javax.ws.rs.core.MediaType;

import com.fatwire.rest.beans.AssetBean;
import com.fatwire.rest.beans.Attribute;
import com.fatwire.rest.beans.Attribute.Data;
import com.fatwire.rest.beans.ErrorBean;
import com.fatwire.rest.beans.Parent;
import com.fatwire.wem.sso.SSO;
import com.fatwire.wem.sso.SSOException;
import com.fatwire.wem.sso.SSOSession;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.fatwire.wem.sso.cas.conf.CASConfig;

/**
 * <p>
 * Sample JAVA class to demonstrate creation of new Flex assets using REST API
 * exposed by Fatwire WEM module.
 * </p>
 * <p>
 * For this class to function, the following are the pre-requisites:
 * <ol>
 * <li>The following jars are required in the classpath:
 * <ul>
 * <li>rest-api.jar</li>
 * <li>wem-sso-api.jar</li>
 * <li>jersey-client.jar</li>
 * <li>jsr311-api.jar</li>
 * <li>jersey-client.jar</li>
 * <li>jersey-core.jar</li>
 * </ul>
 * </li>
 * <li>The following configuration file is required in the classpath (in the
 * example, the above file is referred to as <tt>ExampleCASConfig.xml</tt>.):
 * 
 * <pre>
 * &lt;?xml version="1.0" encoding="UTF-8"?&gt;
 * &lt;beans
 *      xmlns="http://www.springframework.org/schema/beans"
 *      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 *      xmlns:context="http://www.springframework.org/schema/context"
 *      xsi:schemaLocation="http://www.springframework.org/schema/beans
 *                          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 *                          http://www.springframework.org/schema/context
 *                          http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;
 *   &lt;!-- DONOT CHANGE: Single Sign On provider --&gt;
 *   &lt;bean id="ssoprovider" class="com.fatwire.wem.sso.cas.CASProvider"&gt;
 *     &lt;property name="config" ref="ssoconfig" /&gt;
 *   &lt;/bean&gt;
 *   &lt;!--
 *      Single Sign On configuration: change ONLY the following property:
 *          casUrl - URL of the CAS installation
 *   --&gt;
 *   &lt;bean id="ssoconfig" class="com.fatwire.wem.sso.cas.conf.CASConfig"&gt;
 *     &lt;property name="casUrl" value="${cas-url}" /&gt;
 *     &lt;property name="casRestPath" value="/v1" /&gt;
 *   &lt;/bean&gt;
 * &lt;/beans&gt;
 * </pre>
 * 
 * </li>
 * <li>The Content Server Installation must have the "FirstSiteII" sample site
 * and the "Product_C" asset type. "Product_C" should be enabled in
 * "FirstSiteII". There should not be an asset by the name of "Test Product_C"
 * which is the name of the test asset.</li>
 * </ol>
 * 
 * @author Saikat Chaudhuri
 */
public final class CreateAsset
{

    /**
     * Main method. Run this method to create a basic asset using:
     * <ul>
     * <li>{@link #createUsingPut()}</li>
     * <li>{@link #createUsingPost()}</li>
     * </ul>
     * 
     * @param args
     */
    public static void main(String[] args)
    {
        createUsingPut();
       // createUsingPost();
    }



    /**
     * Run this method to create a basic asset using PUT.
     */
    public static void createUsingPut()
    {
        // Step 1: Initiate Jersey client
        Client client = Client.create();

        // Step 2: Create a WebResource with the base URL
        WebResource webResource =
            client.resource("http://127.0.0.1:9080/cs/REST");

        // Step 3: Authenticate over SSO-CAS to acquire a ticket specific to a
        // service or a multi-ticket over multiple services.
        SSOSession ssoSession = null;
        String multiticket = null;
        try
        {
            ssoSession = SSO.getSSOSession("ExampleCASConfig.xml");
            multiticket = ssoSession.getMultiTicket("fwadmin", "xceladmin");
        }
        catch (SSOException e)
        {
            // Troubleshooting SSOException
            // ============================
            //
            // Cause: CAS is not running.
            // Remedy: Deploy CAS and start up the application server for CAS
            // webapp.
            //
            // Cause: CAS is not configured.
            // Remedy: Verify that the URL in the CAS config file,
            // ExampleCASConfig.xml, is reachable.
            //
            // Cause: Username / password is invalid.
            // Remedy: Use valid username / password to authenticate against
            // CAS.

            // Handle exception
            e.printStackTrace();
        }

        // Step 4: Provide the ticket into the REST request
        webResource = webResource.queryParam("multiticket", multiticket);

        // Trying to create a Flex asset for the Flex asset type
        // "Product_C" in the CS site "FirstSiteII"
        String flexAssetSiteName = "FirstSiteII";
        String flexAssetTypeName = "Product_C";

        // Step 5: Specify the REST Resource URL into the WebResource
        // For creating assets of type {typename} in the CS site {sitename},
        // this is: {base_url}/sites/{sitename}/types/{typename}/assets/0
        webResource =
            webResource.path("sites").path(flexAssetSiteName).path("types")
                .path(flexAssetTypeName).path("assets").path("0");

        // Step 6: Create a Builder and set the desired response type
        // Supported response types are:
        // MediaType.APPLICATION_XML, or,
        // MediaType.APPLICATION_JSON
        Builder builder = webResource.accept(MediaType.APPLICATION_XML);

        // Step 7: Instantiate and define the AssetBean for the asset
        AssetBean sourceAsset = new AssetBean();

        // Name - mandatory field
        sourceAsset.setName("Test Product_C PUT");

        // Description - optional field
        sourceAsset.setDescription("Test Product_C PUT description");

        // Add attributes / associations / parents as in the Asset type
        // definition
        Attribute sourceAssetAttribute = new Attribute();
        Data sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIISKU");
        sourceAssetAttributeData.setStringValue("Test SKU");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIILongDescription");
        sourceAssetAttributeData.setStringValue("Test Long Description");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIIPrice");
        sourceAssetAttributeData.setDoubleValue(10.00);
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIIImage");
        sourceAssetAttributeData.setStringValue("Media_C:1114083738411");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        Parent parent = new Parent();
        parent.setParentDefName("FSIIManufacturer");
        parent.getAssets().add("Product_P:1114083739006");
        sourceAsset.getParents().add(parent);

        parent = new Parent();
        parent.setParentDefName("FSIISubcategory");
        parent.getAssets().add("Product_P:1114083739104");
        sourceAsset.getParents().add(parent);

        // Required: Must specify the site(s) for the asset
        sourceAsset.getPublists().add(flexAssetSiteName);

        // Required: Must specify the sub type for the Flex asset type
        sourceAsset.setSubtype("FSII Product");

        // Step 8: Invoke the REST request to create the asset
        AssetBean resultAsset = builder.put(AssetBean.class, sourceAsset);

        // If the REST call encounter a server side exception, the client
        // receives a UniformInterfaceException at runtime.


        // Troubleshooting UniformInterfaceException
        // =========================================
        //
        // Cause: HTTP 403: User does not have permission to access the REST
        // resource.
        // Remedy: Use an authorized CAS user to use this REST resource.
        //
        // Cause: HTTP 404: Either site and/or asset type does not exist, or the
        // asset type is not enabled in the site.
        // Remedy: Verify existence of the site and/or asset type, if necessary
        // create the site and/or type and make sure that the type is enabled in
        // the site.
        //
        // Cause: HTTP 500: Generic server side exception.
        // Remedy: Verify that the source AssetBean has been provided with all
        // mandatory attributes, associations as per type definition, verify
        // that at least one site has been provided in the publist attribute of
        // the AssetBean.
        //
        // Cause: UnmarshalException.
        // Remedy: Verify that the correct bean has been provided in the
        // argument for put().
    }

    /**
     * Run this method to create a basic asset using POST.
     */
    public static void createUsingPost()
    {

        // Step 1: Initiate Jersey client
        Client client = Client.create();

        // Step 2: Create a WebResource with the base URL
        WebResource webResource =
            client.resource("http://127.0.0.1:9080/cs/REST");

        // Step 3: Authenticate over SSO-CAS to acquire a ticket specific to a
        // service or a multi-ticket over multiple services.
        SSOSession ssoSession = null;
        String multiticket = null;
        try
        {
            ssoSession = SSO.getSSOSession("ExampleCASConfig.xml");
            multiticket = ssoSession.getMultiTicket("fwadmin", "xceladmin");
        }
        catch (SSOException e)
        {
            // Troubleshooting SSOException
            // ============================
            //
            // Cause: CAS is not running.
            // Remedy: Deploy CAS and start up the application server for CAS
            // webapp.
            //
            // Cause: CAS is not configured.
            // Remedy: Verify that the URL in the CAS config file,
            // ExampleCASConfig.xml, is reachable.
            //
            // Cause: Username / password is invalid.
            // Remedy: Use valid username / password to authenticate against
            // CAS.

            // Handle exception
            e.printStackTrace();
        }

        // Step 4: Provide the ticket into the REST request
        webResource = webResource.queryParam("multiticket", multiticket);

        // Trying to create a Flex asset for the Flex asset type
        // "Product_C" in the CS site "FirstSiteII"
        String flexAssetSiteName = "FirstSiteII";
        String flexAssetTypeName = "Product_C";

        // Step 5: Specify the REST Resource URL into the WebResource
        // For creating assets of type {typename} in the CS site {sitename},
        // this is: {base_url}/sites/{sitename}/types/{typename}/assets
        webResource =
            webResource.path("sites").path(flexAssetSiteName).path("types")
                .path(flexAssetTypeName).path("assets");

        // Step 6: Create a Builder and set the desired response type
        // Supported response types are:
        // MediaType.APPLICATION_XML, or,
        // MediaType.APPLICATION_JSON
        Builder builder = webResource.accept(MediaType.APPLICATION_XML);

        // Step 7: Instantiate and define the AssetBean for the asset
        AssetBean sourceAsset = new AssetBean();

        // Name - mandatory field
        sourceAsset.setName("Test Product_C POST");

        // Description - optional field
        sourceAsset.setDescription("Test Product_C POST description");

        // Add attributes / associations / parents as in the Asset type
        // definition
        Attribute sourceAssetAttribute = new Attribute();
        Data sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIISKU");
        sourceAssetAttributeData.setStringValue("Test SKU");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIILongDescription");
        sourceAssetAttributeData.setStringValue("Test Long Description");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIIPrice");
        sourceAssetAttributeData.setDoubleValue(10.00);
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        sourceAssetAttribute = new Attribute();
        sourceAssetAttributeData = new Data();
        sourceAssetAttribute.setName("FSIIImage");
        sourceAssetAttributeData.setStringValue("Media_C:1114083738411");
        sourceAssetAttribute.setData(sourceAssetAttributeData);
        sourceAsset.getAttributes().add(sourceAssetAttribute);

        Parent parent = new Parent();
        parent.setParentDefName("FSIIManufacturer");
        parent.getAssets().add("Product_P:1114083739006");
        sourceAsset.getParents().add(parent);

        parent = new Parent();
        parent.setParentDefName("FSIISubcategory");
        parent.getAssets().add("Product_P:1114083739104");
        sourceAsset.getParents().add(parent);

        // Required: Must specify the site(s) for the asset
        sourceAsset.getPublists().add(flexAssetSiteName);

        // Required: Must specify the sub type for the Flex asset type
        sourceAsset.setSubtype("FSII Product");

        // Step 8: Invoke the REST request to create the asset
        ClientResponse resp = builder.post(ClientResponse.class, sourceAsset);

        // The "Location" header provides the element URI
        // which can be used to read back the asset which was created.
        String elementURI = resp.getHeaders().get("Location").get(0);

        // If the REST call encounter a server side exception, the client
        // receives a UniformInterfaceException at runtime.

        // Troubleshooting UniformInterfaceException
        // =========================================
        //
        // Cause: HTTP 403: User does not have permission to access the REST
        // resource.
        // Remedy: Use an authorized CAS user to use this REST resource.
        //
        // Cause: HTTP 404: Either site and/or asset type does not exist, or the
        // asset type is not enabled in the site.
        // Remedy: Verify existence of the site and/or asset type, if necessary
        // create the site and/or type and make sure that the type is enabled in
        // the site.
        //
        // Cause: HTTP 500: Generic server side exception.
        // Remedy: Verify that the source AssetBean has been provided with all
        // mandatory attributes, associations as per type definition, verify
        // that at least one site has been provided in the publist attribute of
        // the AssetBean.
        //
        // Cause: UnmarshalException.
        // Remedy: Verify that the correct bean has been provided in the
        // argument for post().
    }
}

添加JAR 我搜索了JSK中示例注释中提到的每个JAR名称 安装目录并添加它们。

JARs:

  • Jersey的客户端 - 1.1.4.1.jar
  • Jersey的芯 - 1.1.4.1.jar
  • jsr311-api-1.1.1.jar
  • REST的API-11.1.1.8.0.jar
  • WEM-SSO-API-11.1.1.8.0.jar

显然我们还需要这些JAR但未提及:

  • CAS-客户芯3.1.9.jar
  • WEM-SSO-API-CAS-11.1.1.8.0.jar
  • spring 2.5.6.jar
  • 共享记录-1.1.1.jar

从源代码注释中,我在ssoconfig中提取了要用作spring配置的XML文件 bean添加了casUrl值,并将casRestPath的属性名称更改为restPath 在课堂上不存在。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                          http://www.springframework.org/schema/context
                          http://www.springframework.org/schema/context/spring-context-2.5.xsd">


    <!-- DONOT CHANGE: Single Sign On provider -->
    <bean id="ssoprovider" class="com.fatwire.wem.sso.cas.CASProvider">
        <property name="config" ref="ssoconfig"/>
    </bean>



    <!-- Single Sign On configuration: change ONLY the following property: casUrl 
        - URL of the CAS installation -->
    <bean id="ssoconfig" class="com.fatwire.wem.sso.cas.conf.CASConfig">
        <property name="casUrl" value="http://127.0.0.1:9080/cas" />
        <property name="restPath" value="/v1" />
    </bean>


</beans>

异常我运行POST方法:

Jan 08, 2014 5:43:50 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4c08964: startup date [Wed Jan 08 17:43:50 GMT+02:00 2014]; root of context hierarchy
Jan 08, 2014 5:43:50 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ExampleCASConfig.xml]
Jan 08, 2014 5:43:50 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3c200d0: defining beans [ssoprovider,ssoconfig]; root of factory hierarchy
Exception in thread "main" com.sun.jersey.api.client.UniformInterfaceException: PUT http://127.0.0.1:9080/cs/REST/sites/FirstSiteII/types/Product_C/assets/0?multiticket=multi-ST-39-DPgghOvnBCAAggKLAHpa-_tmp_1374099243365 returned a response status of 401
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:563)
    at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:69)
    at com.sun.jersey.api.client.WebResource$Builder.put(WebResource.java:475)
    at com.fatwire.rest.samples.flex.CreateAsset.createUsingPut(CreateAsset.java:222)
    at com.fatwire.rest.samples.flex.CreateAsset.main(CreateAsset.java:97)

在调试时我发现响应状态为401。

异常我运行PUT方法:

Jan 09, 2014 12:03:36 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4c08964: startup date [Thu Jan 09 12:03:36 GMT+02:00 2014]; root of context hierarchy
Jan 09, 2014 12:03:36 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ExampleCASConfig.xml]
Jan 09, 2014 12:03:36 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3c200d0: defining beans [ssoprovider,ssoconfig]; root of factory hierarchy
Exception in thread "main" com.sun.jersey.api.client.UniformInterfaceException: PUT http://127.0.0.1:9080/cs/REST/sites/FirstSiteII/types/Product_C/assets/0?multiticket=multi-ST-7-kejMYvRWO1cua39MfPYn-_tmp_1374099243365 returned a response status of 401
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:563)
    at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:69)
    at com.sun.jersey.api.client.WebResource$Builder.put(WebResource.java:475)
    at com.fatwire.rest.samples.flex.CreateAsset.createUsingPut(CreateAsset.java:222)
    at com.fatwire.rest.samples.flex.CreateAsset.main(CreateAsset.java:97)

没有与代码中名称相同的现有资产。 fwadmin用户已经过测试,但是JSK的默认配置以及将其添加到所有安全组和角色(包括REST ofcourse)之后。 样本中所有使用过的资产ID(对于父母等)都检查出来,它们存在。

1 个答案:

答案 0 :(得分:0)

不知道新代码(11.1.1.8.0),但是这个旧的(11.1.1.6.0)代码不能处理CSRF保护令牌,新版本的站点添加了CSRF保护过滤器,所以我们可以从代码中处理令牌(在新代码中使用):

    //Add the CSRF header (between steps 6 & 7).
    builder = builder.header("X-CSRF-Token", multiticket);

11.1.1.8.0代码位置

  

WCS_Sites / misc / Samples / WEM样本/ REST API样本/ Flex   资产/ COM / FatWire公司/休息

或将其余请求模式添加到/ WEB-INF / classes文件夹中ReqAuthConfig.xml文件中的过滤器例外列表

    <property name="excludedURLs">
        <!--  URLs in this section would be excluded from CSRF protection-->
        <!--  For example to exclude rest calls add <value>/REST/**</value> in the list-->
       <list>
        <value>/ContentServer?[pagename=fatwire/wem/sso/ssoLogin|OpenMarket/Xcelerate/Actions/ProcessQueue|OpenMarket/Xcelerate/Actions/CleanTempObjects|OpenMarket/Xcelerate/Search/Event,#]</value>   
        <value>/CatalogManager?[ftcmd=login,#]</value>
        <value>/FlushServer</value>
        <value>/CacheServer</value>
        <value>/cachetool/inventory.jsp</value>
        <value>/Inventory</value>
      </list>
    </property>