Сайты Webcenter Создание активов REST API с использованием исключений POST и PUT, статус ответа 401
Намерение состоит в том, чтобы создать ресурс, используя код Java и API REST для сайтов.
Во-первых, я не смог найти примеры REST API нигде в установочных или даже исходных каталогах сайтов 11.1.1.8.0 или JSK. Вместо этого я нашел образцы на сервере 11.1.1.6.0.
Код, который я запускаю после изменения базового URL в методах POSt и PUT:
/*
* $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>
* <?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="${cas-url}" />
* <property name="casRestPath" value="/v1" />
* </bean>
* </beans>
* </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-файлы, я искал каждое имя JAR, упомянутое в примерах комментариев в каталоге установки JSK, и добавлял их.
Банки:
- Джерси-клиент-1.1.4.1.jar
- Джерси-ядро-1.1.4.1.jar
- jsr311-апи-1.1.1.jar
- Остальные-апи-11.1.1.8.0.jar
- ОРЭ-SSO-апи-11.1.1.8.0.jar
Видимо, эти JAR-файлы нам также были нужны, но не упомянуты:
- КАС-клиент-ядро-3.1.9.jar
- ОРЭ-SSO-апи-саз-11.1.1.8.0.jar
- весна 2.5.6.jar
- Обще-каротаж 1.1.1.jar
Из комментариев исходного кода я извлек файл XML, который будет использоваться в качестве весенней конфигурации, в bean-компонент ssoconfig добавил значение 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). Все используемые идентификаторы активов в образце (для родителей и т. Д.) Проверяются, они существуют.
1 ответ
Не знаю о новом коде (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/ Образцы / Образцы WEM / Образцы API REST /Flex Assets/com/fatwire/rest
или добавьте шаблоны запросов на отдых в список исключений фильтра в файле ReqAuthConfig.xml в папке /WEB-INF/classes
<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>