22 ago 2011

Autenticación de PROXY NTLM en Weblogic

Recientemente estuve viendo como un simple proxy de salida de internet me estuvo dando problemas durante más de una semana para configurarlo en una aplicación web desplegada en Weblogic.


Recopilando un poco de información por internet por fin dimos con la clave para conseguir que la aplicación se conectara al exterior.


En primer lugar debemos de arrancar Weblogic con la variable de entorno PROXY_SETTINGS configurada. Esto hará que los script's de arranque del servidor de aplicaciones añaden dicha línea como parámetros de ejecución.


Ejemplo:

PROXY_SETTINGS="
-Dhttp.proxySet=true
-Dhttp.proxyHost=<proxy hostname o ip>
-Dhttp.proxyPort=<puerto proxy>
-Dhttp.proxyUser=<mi usuario>
-Dhttp.proxyPassword=<mi password>
-Dweblogic.webservice.transport.http.proxy.host=<proxy hostname o ip>
-Dweblogic.webservice.transport.https.proxy.host=<proxy hostname o ip>
-Dweblogic.webservice.transport.http.proxy.port=<puerto proxy>
-Dweblogic.webservice.transport.https.proxy.port=<puerto proxy>
-Dhttp.nonProxyHosts=\"localhost|127.0.0.1"
-DUseSunHttpHandler=true"



export PROXY_SETTINGS


De esta forma las variables de entorno están ya configuradas. Reiniciamos nuestro Weblogic o las ponemos en el propio script de arranque y reiniciamos.


Aparte de la configuración de Weblogic nos vimos obligados a incluir un código en nuestra aplicación que reescribia el authenticator del proceso Java que estaba corriendo en la JVM. Este paso sólo es necesario si tu aplicación utiliza tecnología ADF.


Antes de realizar una llamada HTTP invocaba el siguiente método:

//Proxy Weblogic
Proxy.getInstance().setup();


El código de la clase Proxy es:

public class Proxy
{
  private static final Logger logger = Logger.getLogger(Proxy.class);
  private static Proxy instance = null;
  private boolean enabled = false;


  public Proxy()
  {
    super();
  }


  public static Proxy getInstance()
  {
    if (instance == null)
      instance = new Proxy();


    return instance;
  }


  public void setup()
  {
    String proxySet = System.getProperty("http.proxySet");


    if (proxySet != null && proxySet.equals("true") && enabled == false)
    {
      String user = System.getProperty("http.proxyUser");
      String password = System.getProperty("http.proxyPassword");


      Authenticator.setDefault(new MyAuthenticator(user, password));
      logger.info("Proxy activado:" + proxySet);
      logger.info("Proxy usuario:" + user);
      logger.info("Proxy password:" + password);
      enabled = true;
    }
  }


  class MyAuthenticator extends Authenticator
  {
    private String username;
    private String password;


    public MyAuthenticator(String username, String password)
    {
      this.username = username;
      this.password = password;
    }


    public PasswordAuthentication getPasswordAuthentication()
    {
      return new PasswordAuthentication(username, password.toCharArray());
    }
  }
}








SSXA + RIDC en un Servlet

Durante un desarrollo de un sitio web en tecnología SiteStudio for external applications (SSXA en adelante) me vi con la necesidad de utilizar el pool de conexiones RIDC que automáticamente cada aplicación Web SSXA tiene definida. 
En concreto no fuimos capaces de descargar un fichero en su formato "original" ya que la tecnología SSXA sólo parece contemplar la descarga de ficheros en su formato web desde UCM (web rendition). Por ello desarrollamos este servlet que es capaz de conectarse a UCM a través de RIDC y realizar una descarga de un fichero dado su identificador (dDocName).


Os dejo un ejemplo de como se realiza una llamada RIDC desde un servlet aprovechando su configuración de conexiones con UCM.




Ejemplo de RIDC usando un Servlet y SSXA:

private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
{
if(request.getParameter("file")!=null && request.getParameter("file")!= ""){
try
{
 ClientApplication client = getWcmApplication(this.getServletContext());
 IdcClientFactory idcClientFact = new IdcClientFactory(client.getConfigLoader().getConfiguration().getSystemConfig().getIdcConfig());
 IdcClient m_client = idcClientFact.getClientManager().createClient(idcClientFact.getIdcConfig().getConnectionUrl());
 IdcContext m_userContext = idcClientFact.getGuestContext();

//Ejecución del servicio
DataBinder dataBinder = m_client.createBinder();

dataBinder.putLocal("IdcService", "GET_FILE");
dataBinder.putLocal("dDocName", request.getParameter("file"));
dataBinder.putLocal("RevisionSelectionMethod","LatestReleased");
dataBinder.putLocal("Rendition", "Primary");

 // Ejecuto la petición
 ServiceResponse sRes = m_client.sendRequest(m_userContext, dataBinder);
 String startSplit = "filename=";
 String content = sRes.getHeader(HEADER_CONTENT);
 String fileName = content.substring(content.indexOf(startSplit) + startSplit.length() + 1, content.length() - 1);

 response.setContentType( (sRes.getHeader(HEADER_MIME) != null) ? sRes.getHeader(HEADER_MIME) : "application/octet-stream" );
 response.setContentLength(Integer.parseInt(sRes.getHeader(HEADER_LENGTH)));
 response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"" );


 //
 //  Stream to the requester.
 //
 byte[] bbuf = new byte[512];
 DataInputStream in = new DataInputStream(sRes.getResponseStream());
 int length   = 0;
 while ((in != null) && ((length = in.read(bbuf)) != -1))
 {
 response.getOutputStream().write(bbuf,0,length);
 }


 in.close();
 response.getOutputStream().flush();
 response.getOutputStream().close(); 
}
catch (ApplicationException e) {
logger.error("Error en descarga de contenido",e);
}
catch (Exception e) {
 logger.error("Error en descarga de contenido",e);
}
}
}


public ClientApplication getWcmApplication(ServletContext sc) throws Exception

  return ServletApplicationFactory.createInstance(sc);
}