Trabalhando com Filtros no WebCenter Content (componente de exemplo)

Neste post iremos conhecer o recurso de Filtros do WebCenter Content. Ao final do artigo, você  irá encontrar um componente de exemplo, com o código fonte.

Filtros são classes Java executadas quando ocorrem determinados eventos no Content Server. O livro do Bex é leitura obrigatória para quem vai trabalhar com Filtros; o apêndice H é dedicado a descrever os Filtros existentes no repositório e, mesmo tendo sido escrito para a versão 7.5, ainda pode ser usado como base para o estudo, embora algumas coisas tenham mudado. Uma lista de alguns Filtros disponíveis na 11g pode ser encontrada no componente HowToComponents.

Os Filtros são usados quando precisamos introduzir uma lógica customizada durante a execução de algum recurso padrão do Content Server; por exemplo, precisamos validar alguns metadados antes que o check-in seja concluído, ou precisamos modificar o mecanismo de login para conceder (ou retirar) permissões para um grupo de usuários logo após a autenticação. No meu caso, a necessidade era evitar que determinados usuários pudessem fazer download de plantas AutoCAD.

O requerimento do cliente era: usuários que não forem da área de Engenharia podem buscar e visualizar os documentos, mas não podem fazer download do arquivo nativo (.dwg), apenas da conversão (PDF ou HTML). Como sabemos, o Content Server não separa a política de segurança entre o arquivo nativo e o convertido; basicamente, o usuário vai ver tudo ou não vai ver nada… para mudarmos este comportamento, precisamos customizar o Content Server.

Uma opção seria modificar a tela de Content Information, avaliando as permissões do usuário e ocultando o link do arquivo nativo. Mas esta proteção funcionaria apenas na tela de Content Information, deixando um risco razoável. Isso também não funcionaria para aplicações integrando com o Content Server através de Java ou Web Services.

Portanto a decisão foi implementar através de um Filtro. Para isso, precisamos escrever uma classe Java. A declaração do Filtro precisa seguir este formato:

public class GetFileFilter implements FilterImplementor {
     
public int doFilter(Workspace ws, DataBinder binder, ExecutionContext cxt) throws DataException, ServiceException
   {

return CONTINUE;

}

Os retornos possíveis são CONTINUE, FINISHED ou ABORT, e o que cada um faz vai depender do Filtro que está sendo executado. CONTINUE significa que o código Java foi executado com sucesso, e que o evento que disparou o Filtro pode continuar.

O que a gente quer fazer é interceptar o download do arquivo. Para isso, existe um filtro chamado checkDownloadOverride, que é executado durante algum serviço de download, como o GET_FILE. Agora que já sabemos qual filtro usar, vamos rever as nossas regras.

Iremos trabalhar com 2 restrições: por extensão de arquivo e por Role de usuário. Não queremos restringir o download de todos os documentos do repositório, apenas de algumas extensões (.dwg, etc). E temos que garantir que os usuários da área de Engenharia (e Administradores) possam acessar os arquivos nativos.

O método que executa o Filtro traz um binder com diversas informações. Então já conseguimos pegar as informações sobre qual é o arquivo solicitado e quem é o usuário:

String dUser = binder.getLocal(“dUser”);
String dDocName = binder.getLocal(“dDocName”);
String dID = binder.getLocal(“dID”);
String dExtension = binder.getLocal(“dExtension”);
String idcService = binder.getLocal(“IdcService”);

Em seguida, precisamos verificar se o serviço é o GET_FILE ou o WEBDAV_GET (este é o serviço usado pelo Windows Explorer quando estamos com o DIS), que são serviços executados quando o usuário quer fazer o download de algum arquivo:

if (!idcService.equals(GET_FILE) && !idcService.equals(WEBDAV_GET))
    {
            return CONTINUE;
    }

Existem alguns serviços internos do Content Server que caem no mesmo filtro, por isso esta checagem é importante.

Para facilitar um pouco a vida do administrador do Content Server, iremos criar 2 parâmetros no nosso componente: um que guarda as extensões de arquivos que devem ser protegidas (ExtensionsToControl) e um que guarda as Roles que o usuário precisa ter para conseguir acessar o arquivo nativo (RolesAllowedNative). Este código é usado para trazer o valor do parâmetro:

//Get file extensions that must be monitored
String ExtensionsToControl = “”;
if(SharedObjects.getEnvironmentValue(“ExtensionsToControl”) != null)
ExtensionsToControl = SharedObjects.getEnvironmentValue(“ExtensionsToControl”);  

//Validates file extension
if (ExtensionsToControl.indexOf(dExtension) <=0)
    {
           return CONTINUE;
    }

Em seguida usamos um código parecido para trazer o parâmetro que diz quais Roles o usuário precisa ter para acessar o arquivo. Porém, como estamos falando em mais de uma role, precisamos fazer um loop para testar cada uma:

String RolesAllowedList = “”;
String RolesAllowed[];

//Get roles allowed to download native files
if(SharedObjects.getEnvironmentValue(“RolesAllowedNative”) != null)
    RolesAllowedList = SharedObjects.getEnvironmentValue(“RolesAllowedNative”);       
RolesAllowed = RolesAllowedList.split(“,”);

//Check if user has the roles allowed to access native file
for (int x=0;x<RolesAllowed.length;x++){
        if (SecurityUtils.isUserOfRole(userData, RolesAllowed[x]))
        {
        return true;                  
        }
}

SecurityUtils.isUserOfRole é um método disponibilizado pelo Content Server para validar se o usuário tem uma determinada Role. Nesta validação, caso o usuário tenha pelo menos uma das Roles necessárias, ele poderá baixar o arquivo.

Para compilar este código, você precisa adicionar o arquivo idcserver.jar no classpath do seu projeto. Este arquivo está localizado na pasta do Content Server %MW_HOME%\Oracle_ECM1\ucm\idc\jlib. Uma vez que a nossa classe está pronta, podemos criar o componente (que é necessário para declararmos o Filtro).

A criação do componente é feita pelo Component Wizard (se você nunca criou um componente, recomendo este tutorial), da forma tradicional. A única diferença é que precisamos declarar o filtro, e isso é feito no arquivo .hda do componente. Procure esta seção:

@ResultSet Filters
4
type
location
parameter
loadOrder
@end

Com a declaração do Filtro, o arquivo ficará assim:

@ResultSet Filters
4
type
location
parameter
loadOrder
checkDownloadOverride
ucmutils.GetFileFilter
null
10
@end

checkDownloadOverride é o Filtro que queremos usar e ucmutils.GetFileFilter é o nome da classe Java que será executada. Não precisamos declarar um método, porque por padrão ele executa o método doFilter.

Também não esqueça de declarar os parâmetros:

image

OBS: O parâmetro SuppressOutputMessages define se as mensagens de debug serão exibidas no output do servidor (false significa que serão exibidas). Para visualizar estas mensagens, acesse o menu Administration –> System Audit Information. Na seção Tracing Sections Information, inclua UCMUtils, marque a opção Save e clique em Update:

image

Depois disso, as mensagens de debug irão aparecer na página View Server Output (o link fica na própria página System Audit Information).

image

Quando um usuário sem permissão tenta acessar o arquivo nativo, o output do servidor também exibe o erro:

image

E o usuário recebe uma mensagem de erro:

image

Esta mensagem aparece porque o nosso código Java lança uma exceção quando o usuário não tem a permissão necessária:

throw new ServiceException(“User does not have permission to download file.”);

Como lançamos a exceção, a mensagem de erro ficará gravada no log. As informações do output do servidor não vão para o log, para não ocuparem espaço em disco.

Para fazer download do componente de exemplo, clique aqui.

Aqui entra o obrigatório disclaimer: Este não é um componente oficial da Oracle. Desta forma, a Oracle não se responsabiliza por qualquer dano ou perda de dados que possam ocorrer devido ao uso do mesmo. O autor (eu!) também se isenta de qualquer responsabilidade.

O código fonte Java está disponível no componente, na pasta Classes. Você pode modificar conforme o escopo da alteração que você precise fazer.

Para o próximo post, iremos mudar de assunto… stay tuned!

This entry was posted in ECM, Oracle. Bookmark the permalink.

2 Responses to Trabalhando com Filtros no WebCenter Content (componente de exemplo)

  1. andrealmar says:

    Denis,

    Como fica a questão de performance com o filtro? Imagino um cenario com milhares de consultas a arquivos .dwg e o filtro trabalhando para cada um desses requests….Abs,

    • Fala André! Essa é uma ótima pergunta. Os filtros são executados pelo core do servidor, então se as são regras de validação forem simples, elas serão executadas sem impacto na performance do servidor. Vários recursos nativos do Content Server são implementados como filtros, então estamos mantendo o padrão de certa forma. Mas é sempre importante validar se o filtro é realmente necessário, porque ele é executado todas as vezes que uma determinada ação acontece, então se o seu código não estiver otimizado, isso pode trazer complicações ao ambiente. Por exemplo, se para cada execução do filtro precisarmos buscar informações em banco de dados ou web services, com certeza o tempo de processamento será longo. Neste caso valeria a pena considerar outras alternativas, como jobs, por exemplo. Resumindo: questione a necessidade do filtro antes de escrever o código🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s