Propagação de Identidade em Web Service

5 respostas
Talles_Santana

Pessoal,
estou com o seguinte cenário:
Uma aplicação java já faz autenticação dos usuários e precisa repassar(propagar a identidade) o id do usuário quando realizar a invocação de um web service(java).
Preciso fazer isso da forma menos intrusiva e mais simples para causar o mínimo de impacto e alteração nas aplicações e/ou web services.

Tive uma idéia para solucionar o problema:
Uma invocação de web service no final das contas é uma mensagem HTTP que tem uma mensagem SOAP no payload.
Assim, a aplicação consumidora do serviço coloca o id do usuário dentro da mensagem SOAP.
O serviço passaria a lidar com a questão de ‘ler’ o id do usuário dentro da mensagem SOAP.

Ambiente de desenvolvimento: Oracle Workshop for WebLogic.
Servidor: Oracle Weblogic Server

Infelizmente, não encontrei recursos no ambiente que me permitam alterar a mensagem de invocação do serviço.

Podem me ajudar com essa tarefa?

Grato,
Talles Santana

5 Respostas

A

Você quer desenvolver um serviço? Ou um cliente para um serviço existente? Nâo deu pra entender muito o seu pronblema

Talles_Santana

Já tenho o serviço e já tenho o cliente do serviço.

O cliente do serviço é uma aplicação que, para desempenhar seu papel, pode realizar uma chamada ao serviço.
Eu quero apenas passar o ID do usuário, que o cliente sabe qual é, para o serviço no momento de sua invocação/chamada.
Gostaria de fazer isso sem alterar a assinatura do serviço.

A

Se este ID não está na assinatura, você tem que alterar. A não ser que você passe isto dentro de algum outro elemento existente e trate isso na implementação do serviço

Talles_Santana

Não dá para ‘incluir’ um elemento na requisição SOAP e o serviço tratar(ler) isso?

Talles_Santana

Então pessoal, seguindo o livro Professional Oracle Weblogic Server criei um serviço(classe) seguindo o modelo code-frist. O código do método do serviço é bem simples, seu funcionamento não é relevante.
Em seguida, criei uma aplicação consumidora do serviço. Ok, tudo funcionando.
Ao introduzir uma política no método do servico(getPoco(int id)), seguindo os moldes do livro, minha classe cliente não funciona mais e ao invocar o serviço é lançada a exceção indicando que a requisição não atende a política. Ok, isso era esperado já que incluí a política.

Então, realizei a alteração necessária na aplicação cliente para incluir o token na mensagem de requisição de modo que atenda a política.
Contudo, ao fazer o downcast (Map<String, Object> rc = ((BindingProvider) port).getRequestContext():wink: dos stubs para obter o contexto da mensagem recebo
uma class cast exception. Já pesquisei na internet, mas até agora não vi nada que pudesse me ajudar. Alguém tem idéia do que seja? Foram os stubs gerados de forma incorreta ou tenho que adicionar algo no código?

Exception in thread “Main Thread” java.lang.ClassCastException: br.propid.clientepoco.wsclient.BuscaPocoService_PortType_Stub
at br.propid.cliente.Consumidor.main(Consumidor.java:35)

Ordem:
criei a classe do serviço, criei o build.xml do serviço e executei.
criei o build.xml do cliente, creiei a classe consumidora do serviço.
Para incluir a politica:
criei o UserTokenPolicy.xml e inclui a anotação na classe do serviço
adicionei, na classe cliente, o código que deveria inserir o token que atende a política

Abaixo, as fontes.

Classe Consumidora do Serviço

package br.propid.cliente;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.rpc.ServiceException;
import javax.xml.ws.BindingProvider;

import localhost_7001.buscapocoservice.Poco;
import weblogic.wsee.security.unt.ClientUNTCredentialProvider;
import weblogic.xml.crypto.wss.WSSecurityContext;
import weblogic.xml.crypto.wss.provider.CredentialProvider;
import br.propid.clientepoco.wsclient.BuscaPocoService_PortType;
import br.propid.clientepoco.wsclient.BuscaPocoService_Service;
import br.propid.clientepoco.wsclient.BuscaPocoService_Service_Impl;

public class Consumidor {

	public static void main(String[] args) throws ServiceException,
			RemoteException {

		try {
			BuscaPocoService_Service service = new BuscaPocoService_Service_Impl(
					"http://localhost:7001/ServicoPoco/BuscaPocoService?wsdl");

		
			BuscaPocoService_PortType port = service.getBuscaPocoServicePort();

			// CODIGO ADICIONADO PARA INCLUIR POLITICA UserToken na mensagem de request.
				List<CredentialProvider> credProviders = new ArrayList<CredentialProvider>();
				CredentialProvider cp = new ClientUNTCredentialProvider("weblogic"
						.getBytes(), "weblogic".getBytes());
				credProviders.add(cp);

                                 // CLASS CAST EXCEPTION
				Map<String, Object> rc = ((BindingProvider) port).getRequestContext();


				rc.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);

			// FIM CODIGO ADICIONADO
			
			
			// Invocação do servico port.getPoco(int id)
			Poco poco = port.getPoco(1);
			// Processar resposta
			if (poco != null) {
				System.out.println("**** POCO ****");
				System.out.println(poco.getId());
				System.out.println(poco.getNome());
				System.out.println(poco.getEstado());
			} else {
				System.out.println("No Property found");
			}
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
			System.out.println(e.getCause());
			e.printStackTrace();
		}
	}

BUILD XML DO CLIENTE

<project default="build-service">
	<taskdef name="clientegen"
		classname="weblogic.wsee.tools.anttasks.ClientGenTask"
		classpath="C:/bea/wlserver_10.3/server/lib/weblogic.jar"/>
	<target name="build-service">
		<clientgen wsdl="http://localhost:7001/ServicoPoco/BuscaPocoService?WSDL"
		   destDir="src" packageName="br.propid.clientepoco.wsclient"/>
	</target>
</project

Classe que representa o Serviço

package br.propid.servico;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

import weblogic.jws.Policy;
import br.propid.beans.Poco;

@WebService(serviceName= "BuscaPocoService", targetNamespace = "http://localhost:7001/BuscaPocoService")
@SOAPBinding(
	style=SOAPBinding.Style.DOCUMENT,
	use=SOAPBinding.Use.LITERAL,
	parameterStyle=SOAPBinding.ParameterStyle.WRAPPED
	)
public class BuscaPocoService {

	@WebMethod
	@Policy(uri="UsernameTokenPolicy.xml", direction=Policy.Direction.inbound)
	public Poco getPoco(int id) {
		
		Poco p = new Poco();
		p.setEstado("Rio de Janeiro");
		p.setNome("poco1");
		p.setId(id);
		return p;
	}
}

BUILD XML DO SERVICO

<?xml version="1.0"?>
<project name="java-project" default="deploy">
	<property environment="env"/>

	<target name="init">
		<property file="local.properties"/>
		<property name="SERVICE-NAME" value="BuscaPocoService"/>
		<property name="SERVICE-IMPL-FOLDER" value="br/propid/servico"/>
		<property name="SERVICE-IMPL-JAVA-FILE" value="${SERVICE-IMPL-FOLDER}/${SERVICE-NAME}.java"/>
		<basename property="APP-NAME" file="${basedir}"/>
		<property name="APP-MODULE" value="${APP-NAME}.ear"/>
		
		<path id="CLASSPATH">
			<pathelement path="build/classes"/>
			<pathelement path="${env.WL_HOME}/server/lib/weblogic.jar"/>
		</path>      
	
		<path id="WLONLY_CLASSPATH"> <!-- for jwsc when using Code-First approach only -->
			<pathelement path="${env.WL_HOME}/server/lib/weblogic.jar"/>
		</path>      

		<taskdef name="wldeploy" classpathref="CLASSPATH" classname="weblogic.ant.taskdefs.management.WLDeploy"/>
		<taskdef name="jwsc" classpathref="CLASSPATH" classname="weblogic.wsee.tools.anttasks.JwscTask"/>
	</target>

	<target name="clean" depends="init">
		<delete>
			<fileset dir="build" includes="**/*.*"/>
		</delete>
		<delete dir="build/classes"/>
		<delete dir="tmp"/>
	</target>

	<target name="compile" depends="init">
		<mkdir dir="build/classes"/>
		<javac srcdir="src" destdir="build/classes" classpathref="CLASSPATH" debug="on" includes="**/*.java"/>
	</target>	

	<target name="package" depends="compile">
		<delete file="build/${APP-MODULE}"/>
		<mkdir dir="tmp/earcontents"/>
		<jwsc srcdir="src" destdir="tmp/earcontents" classpathref="WLONLY_CLASSPATH" compiler="extJavac" keepGenerated="false" debug="on">
			<jws file="${SERVICE-IMPL-JAVA-FILE}" contextpath="${APP-NAME}" type="JAXWS"/>
		</jwsc>
		<ear destfile="build/${APP-MODULE}" appxml="tmp/earcontents/META-INF/application.xml">
			<fileset dir="tmp/earcontents">
				<exclude name="META-INF/application.xml" />
			</fileset>
		</ear>
		<delete dir="tmp/earcontents"/>
	</target>

	 <target name="deploy" depends="package">
		<wldeploy action="deploy" upload="true" source="build/${APP-MODULE}" name="${APP-NAME}" user="${weblogic.user}" password="${weblogic.password}" adminurl="${weblogic.adminurl}" verbose="false" debug="false"/> 
		<delete dir="config"/>
		<echo message="Deployed Web Service. Path for WSDL and test client access is: http://host:port/${APP-NAME}/${SERVICE-NAME}"/>
	</target>

	<target name="undeploy" depends="init">
		<wldeploy action="undeploy" name="${APP-NAME}" user="${weblogic.user}" password="${weblogic.password}" adminurl="${weblogic.adminurl}" verbose="false" debug="false"/>
	</target>
	
</project>

UsernameTokenPolicy.xml

<?xml version="1.0"?>
<wsp:Policy xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
	<sp:SupportingTokens>
		<wsp:Policy>
			<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
		</wsp:Policy>
	</sp:SupportingTokens>
</wsp:Policy>
Criado 10 de fevereiro de 2011
Ultima resposta 20 de fev. de 2011
Respostas 5
Participantes 2