Desenvolvedores criando integrações que exigem acesso programático ao AEM as a Cloud Service precisam de uma maneira simples e rápida de obter tokens de acesso temporário para o AEM a fim de facilitar as atividades de desenvolvimento locais. Para atender a essa necessidade, o Console do desenvolvedor do AEM permite que os desenvolvedores gerem tokens de acesso temporários que podem ser usados para acessar o AEM de forma programática.
O Token de acesso de desenvolvimento local fornece acesso aos serviços de publicação e criação do AEM como o usuário que gerou o token, juntamente com suas permissões. Apesar de este ser um token de desenvolvimento, não compartilhe este token ou armazene no controle do código-fonte.
accessToken
e salve o arquivo JSON em um local seguro na máquina de desenvolvimento.
Criaremos um aplicativo JavaScript externo simples para ilustrar como acessar programaticamente o AEM as a Cloud Service por HTTPS usando o token de acesso do desenvolvedor local. Isso ilustra como qualquer aplicativo ou sistema executado fora do AEM, independentemente da estrutura ou linguagem, pode usar o token de acesso para realizar a autenticação programaticamente no AEM as a Cloud Service e acessá-lo. No próxima seção, atualizaremos esse código de aplicativo para dar suporte à abordagem de geração de um token para uso de produção.
Esse aplicativo de amostra é executado a partir da linha de comando e atualiza os metadados de ativos AEM usando APIs HTTP do AEM Assets, usando o seguinte fluxo:
getCommandLineParams()
)getAccessToken(...)
)listAssetsByFolder(...)
)updateMetadata(...)
)O elemento principal na autenticação programática para o AEM usando o token de acesso é adicionar um cabeçalho de solicitação HTTP de autorização a todas as solicitações HTTP feitas no AEM, no seguinte formato:
Authorization: Bearer ACCESS_TOKEN
Assegure que Node.js O está instalado na máquina de desenvolvimento local, usada para executar o aplicativo externo
Baixe e descompacte o aplicativo externo de amostra
Na linha de comando, na pasta deste projeto, execute npm install
Copie o baixou o token de acesso de desenvolvimento local para um arquivo chamado local_development_token.json
na raiz do projeto
Abertura index.js
e revise o código do aplicativo externo e os comentários.
const fetch = require('node-fetch');
const fs = require('fs');
const auth = require('@adobe/jwt-auth');
// The root context of the Assets HTTP API
const ASSETS_HTTP_API = '/api/assets';
// Command line parameters
let params = { };
/**
* Application entry point function
*/
(async () => {
console.log('Example usage: node index.js aem=https://author-p1234-e5678.adobeaemcloud.com propertyName=metadata/dc:rights "propertyValue=WKND Limited Use" folder=/wknd-shared/en/adventures/napa-wine-tasting file=credentials-file.json' );
// Parse the command line parameters
params = getCommandLineParams();
// Set the access token to be used in the HTTP requests to be local development access token
params.accessToken = await getAccessToken(params.developerConsoleCredentials);
// Get a list of all the assets in the specified assets folder
let assets = await listAssetsByFolder(params.folder);
// For each asset, update it's metadata
await assets.forEach(asset => updateMetadata(asset, {
[params.propertyName]: params.propertyValue
}));
})();
/**
* Returns a list of Assets HTTP API asset URLs that reference the assets in the specified folder.
*
* https://experienceleague.adobe.com/docs/experience-manager-cloud-service/assets/admin/mac-api-assets.html?lang=en#retrieve-a-folder-listing
*
* @param {*} folder the Assets HTTP API folder path (less the /content/dam path prefix)
*/
async function listAssetsByFolder(folder) {
return fetch(`${params.aem}${ASSETS_HTTP_API}${folder}.json`, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + params.accessToken // Provide the AEM access token in the Authorization header
},
})
.then(res => {
console.log(`${res.status} - ${res.statusText} @ ${params.aem}${ASSETS_HTTP_API}${folder}.json`);
// If success, return the JSON listing assets, otherwise return empty results
return res.status === 200 ? res.json() : { entities: [] };
})
.then(json => {
// Returns a list of all URIs for each non-content fragment asset in the folder
return json.entities
.filter((entity) => entity['class'].indexOf('asset/asset') === -1 && !entity.properties.contentFragment)
.map(asset => asset.links.find(link => link.rel.find(r => r === 'self')).href);
});
}
/**
* Update the metadata of an asset in AEM
*
* https://experienceleague.adobe.com/docs/experience-manager-cloud-service/assets/admin/mac-api-assets.html?lang=en#update-asset-metadata
*
* @param {*} asset the Assets HTTP API asset URL to update
* @param {*} metadata the metadata to update the asset with
*/
async function updateMetadata(asset, metadata) {
await fetch(`${asset}`, {
method: 'put',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + params.accessToken // Provide the AEM access token in the Authorization header
},
body: JSON.stringify({
class: 'asset',
properties: metadata
})
})
.then(res => {
console.log(`${res.status} - ${res.statusText} @ ${asset}`);
});
}
/**
* Parse and return the command line parameters. Expected params are:
*
* - aem = The AEM as a Cloud Service hostname to connect to.
* Example: https://author-p12345-e67890.adobeaemcloud.com
* - folder = The asset folder to update assets in. Note that the Assets HTTP API do NOT use the JCR `/content/dam` path prefix.
* Example: '/wknd-shared/en/adventures/napa-wine-tasting'
* - propertyName = The asset property name to update. Note this is relative to the [dam:Asset]/jcr:content node of the asset.
* Example: metadata/dc:rights
* - propertyValue = The value to update the asset property (specified by propertyName) with.
* Example: "WKND Free Use"
* - file = The path to the JSON file that contains the credentials downloaded from AEM Developer Console
* Example: local_development_token_cm_p1234-e5678.json
*/
function getCommandLineParams() {
let parameters = {};
// Parse the command line params, splitting on the = delimiter
for (let i = 2; i < process.argv.length; i++) {
let key = process.argv[i].split('=')[0];
let value = process.argv[i].split('=')[1];
parameters[key] = value;
};
// Read in the credentials from the provided JSON file
if (parameters.file) {
parameters.developerConsoleCredentials = JSON.parse(fs.readFileSync(parameters.file));
}
console.log(parameters);
return parameters;
}
async function getAccessToken(developerConsoleCredentials) {s
if (developerConsoleCredentials.accessToken) {
// This is a Local Development access token
return developerConsoleCredentials.accessToken;
}
}
Revise o fetch(..)
invocações no listAssetsByFolder(...)
e updateMetadata(...)
e aviso headers
definir o Authorization
cabeçalho de solicitação HTTP com um valor de Bearer ACCESS_TOKEN
. É assim que a solicitação HTTP originada do aplicativo externo é autenticada no AEM as a Cloud Service.
...
return fetch(`${params.aem}${ASSETS_HTTP_API}${folder}.json`, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + params.accessToken // Provide the AEM access token in the Authorization header
},
})...
Qualquer solicitação HTTP para AEM as a Cloud Service deve definir o token de acesso do portador no cabeçalho Autorização. Lembre-se de que cada ambiente do AEM as a Cloud Service requer seu próprio token de acesso. O token de acesso do desenvolvimento não funciona no preparo ou na produção, o do preparo não funciona no desenvolvimento ou na produção e o da produção não funciona no desenvolvimento ou no preparo!
Usando a linha de comando, na raiz do projeto, execute a aplicação, transmitindo os seguintes parâmetros:
$ node index.js \
aem=https://author-p1234-e5678.adobeaemcloud.com \
folder=/wknd-shared/en/adventures/napa-wine-tasting \
propertyName=metadata/dc:rights \
propertyValue="WKND Limited Use" \
file=local_development_token.json
Os seguintes parâmetros são transmitidos em:
aem
: o esquema e o nome do host do ambiente as a Cloud Service AEM com o qual o aplicativo interage (por exemplo, https://author-p1234-e5678.adobeaemcloud.com
).folder
: o caminho da pasta de ativos cujos ativos são atualizados com o propertyValue
; NÃO adicione o /content/dam
prefixo (ex. /wknd-shared/en/adventures/napa-wine-tasting
)propertyName
: o nome da propriedade do ativo que será atualizado, em relação a [dam:Asset]/jcr:content
(por exemplo, metadata/dc:rights
).propertyValue
: O valor para definir a variável propertyName
to; valores com espaços precisam ser encapsulados com "
(por exemplo, "WKND Limited Use"
)file
: o caminho relativo do arquivo JSON baixado do Console do desenvolvedor do AEM.Uma execução bem-sucedida da saída de resultados do aplicativo para cada ativo atualizado:
200 - OK @ https://author-p1234-e5678.adobeaemcloud.com/api/assets/wknd-shared/en/adventures/napa-wine-tasting.json
200 - OK @ https://author-p1234-e5678.adobeaemcloud.com/api/assets/wknd-shared/en/adventures/napa-wine-tasting/AdobeStock_277654931.jpg.json
200 - OK @ https://author-p1234-e5678.adobeaemcloud.com/api/assets/wknd-shared/en/adventures/napa-wine-tasting/AdobeStock_239751461.jpg.json
200 - OK @ https://author-p1234-e5678.adobeaemcloud.com/api/assets/wknd-shared/en/adventures/napa-wine-tasting/AdobeStock_280313729.jpg.json
200 - OK @ https://author-p1234-e5678.adobeaemcloud.com/api/assets/wknd-shared/en/adventures/napa-wine-tasting/AdobeStock_286664352.jpg.json
Verifique se os metadados foram atualizados, fazendo logon no ambiente as a Cloud Service AEM (verifique se o mesmo host passou para o aem
parâmetro de linha de comando é acessado).
aem
parâmetro de linha de comando)folder
parâmetro de linha de comando, por exemplo WKND > Inglês > Aventuras > Degustação de Vinho Napametadata/dc:rights
Propriedade JCR, que reflete o valor fornecido na variável propertyValue
parâmetro, por exemplo Uso limitado da WKNDAgora que acessamos programaticamente o AEM as a Cloud Service usando o token de desenvolvimento local. Em seguida, precisamos atualizar o aplicativo para lidar com o uso de Credenciais de serviço, para que esse aplicativo possa ser usado em um contexto de produção.