SSO ASP.NET to WordPress: PHP Souce Code

Este post es la segunda parte del post SSO ASP.NET to WordPress, en donde puedes encontrar la explicación general del proyecto. Aquí puedes encontrar el código fuente PHP utilizado para establecer un 'Single Sign On' (SSO) entre una aplicación web ASP.NET (AppW) y un WordPress (WP).

Tal y como se indica en el post principal, los dos archivos necesarios para el SSO son un PHP (al que llamaré wp-login-asp.php - el nombre puede ser modificado al gusto de cada uno -) y un archivo .cs con las clases del proyecto .NET cuya explicación se encuentra en el post SSO ASP.NET to WordPress: ASP.NET Souce Code.

ARCHIVO wp-login-asp.php

La función principal de este archivo es ejecutar las solicitudes efectuadas desde la Aplicación Web, y realizar las llamadas a los métodos del WP que serán las encargadas de loguear, desloguear o solicitar el estado del login, del usuario actual.

Este archivo debe estar ubicado en el directorio raiz del WP, al mismo nivel que el archivo wp-login.php.


<?PHP
  include 'wp-load.php';
 
  require_once( ABSPATH . WPINC . '/user.php' );
  require_once( ABSPATH . WPINC . '/pluggable.php' );

  function GetXmlData($data_user, $data_error_num, $data_error_text)
  {
    //make XML output
    $temp_xml = '<?xml version="1.0" encoding="UTF-8"?>';
    $temp_xml .= '<object>';
   
    if ($data_error_num<=0) {
      //echo'login failed!';
      $temp_xml .= '<is_valid>'.$data_error_num.'</is_valid>';
      $temp_xml .= '<error_message>'.$data_error_text.'</error_message>';
    } else {
      //set xml data
      $temp_xml .= '<is_valid>1</is_valid>';
      $temp_xml .= '<error_message></error_message>';
      $temp_xml .= '<id>'.$data_user->ID.'</id>';
      $temp_xml .= '<user_login>'.$data_user->user_login.'</user_login>';
      $temp_xml .= '<user_pass>'.$data_user->user_pass.'</user_pass>';
      $temp_xml .= '<user_displayname>'.$data_user->user_firstname.
        ' '.$data_user->user_lastname.'</user_displayname>';
      $temp_xml .= '<user_nicename>'.$data_user->user_nicename.
        '</user_nicename>';
      $temp_xml .= '<user_email>'.$data_user->user_email.'</user_email>';
    }
    $temp_xml .= '</object>'; //close xml data
   
    return $temp_xml;
  }
 
  //get the variables from the post of another page
  $u_action =  $_REQUEST['Action'];
  $u_username = $_REQUEST['UserName'];
  $u_password = $_REQUEST['Pwd'];

  //set DATA XML output variable to export
  $data = "";

  //study cases
  switch ($u_action){
    case "logged_status":
      $current_user = wp_get_current_user();
      if ( 0 == $current_user->ID ) {
        $data = GetXmlData(null, 0, 'Current user is not logged');
      } else {
        $data = GetXmlData($current_user, 1, '');
      }         
      break;

    case "logout":
      wp_logout();
      wp_clear_auth_cookie();
      $data = GetXmlData(null, 0, 'El usuario actual ha finalizado su sesión');
      break;

    case "loggin":
      //build the array
      $creds = array();
      $creds['user_login'] = $u_username;
      $creds['user_password'] = $u_password;
      $creds['remember'] = true;

      //log the user in
      $user = wp_signon( $creds, false );
      $error_num;
      $error_msg = '';
      if ( is_wp_error($user) )
      {
        $error_num = -1;
        $error_msg = $user->get_error_message();
      } else {
          $error_num = 1; //no error
      }
      $data = GetXmlData($user, $error_num, $error_msg);
      break;

    default:
      $data = GetXmlData(null, -1, 'No action is defined');
      break;
  }

  print_r($data);
?>

Si analizamos el código fuente, podremos encontrar los siguientes elementos:

· Función GetXmlData:
Se trata de una función auxiliar, que devuelve una respuesta a la aplicación en formato Xml. Aunque no es necesario que la respuesta se devuelva en este formato, he preferido utilizarlo porque permite una mayor facilidad a la hora de tratar los datos devueltos desde el lado de la AppW asp.net. Simplemente es un wrapper que formatea la información de salida del WP.

· Sentencia SWITCH:
Ejecuta las acciones necesarias en funcion del parametro "Action" enviado desde la AppW. Tal y como cada opcion indica, cada apartado se encarga de: averiguar el estado del usuario actual ('logged_status'), desloguear al usuario actual ('logout') eliminando las cookies de registro, ó autenticar al usuario actual ('loggin').

NOTA IMPORTANTE: Todas estas funciones se ejecutan a petición de la AppW, siendo independientes del proceso de login del WP. Si un usuario se autentica directamente en el WP, se generarán las cookies de su registro, y posteriormente las tendremos que recoger del lado .NET y hacer la llamada a la acción 'logged_status' para obtener los datos del usuario registrado en ese momento. En el .NET Source Code, explico el proceso con más detenimiento.

Puedes obtener más información en:
· SSO ASP.NET to WordPress: Single Sign On
· SSO ASP.NET to WordPress: ASP.NET Souce Code

Un saludo a todos!

[...]

Leer más >>

SSO ASP.NET to WordPress: ASP.NET Souce Code

Este post es la tercera parte del post SSO ASP.NET to WordPress, en donde puedes encontrar la explicación general del proyecto. Aquí puedes encontrar el código fuente ASP.NET utilizado para establecer un 'Single Sign On' (SSO) entre una aplicación web ASP.NET (AppW) y un WordPress (WP).

Tal y como se indica en el post principal, los dos archivos necesarios para el SSO son un PHP cuya explicación se encuentra en el post SSO ASP.NET to WordPress: PHP Souce Code y un archivo .cs (al que llamaré LoginWordPress.cs - el nombre puede ser modificado al gusto de cada uno -) con las clases del proyecto .NET.

ARCHIVO DE CLASES LoginWordPress.cs

El archivo de clases está divido en tres partes bien diferenciadas.

Primero tenemos la estructura básica, que comprende las tres clases juntas y un modelo (aunque ya sabeís que se deberían implementar por separado, según los principios SOLID). Aquí están englobadas todas las clases utilizadas:

1 - Un modelo para la gestión del usuario: LoginUser
2 - Una clase para controlar las Excepciones: LoginWPException
3 - Una clase con metodos auxiliares que controlan la información recibida y la gestión de las cookies
4 - La clase principal con los métodos de acceso al WordPress.

using [...];
namespace Domain.Login.Core
{
    public class LoginUser {}
    public class LoginWPException : Exception {}
    public class LoginWPHelpers {}
    public class LoginWPMethods {}
}

Procedamos a implementar cada una de las clases.

LoginUser
Esta clase, implementa el modelo para gestionar toda la información de los usuarios registrados, y puede modificarse según las necesidades de cada uno. Sirva simplemente para controlar toda la información en un único punto, y facilitar así su uso para la autenticación directa en nuestra aplicación web AppW.

Contiene una serie de atributos para almacenar los datos, unos constructores genéricos y un operador override ToString(), que yo utilizo para almacenar la información del usuario autenticado en HttpContext.Current.User.Identity.Ticket.UserData

Este sería el código fuente final:

   [Serializable]
   public class LoginUser
   {
        public int ID { get; set; }
        public string Login { get; set; }
        public string Pass { get; set; }
        public string NiceName{ get; set; }
        public string Email { get; set; }

        public LoginUser() : this("", "", -1, "", "") { }
        public LoginUser(string _user, string _pass) : this(_user, _pass, -1, "", "") { }
        public LoginUser(string _user, string _pass, int _id, string _nicename, string _email)
        {
            ID = _id;
            Login = _pass;
            Pass = _user;
            NiceName = _nicename;
            Email = _email;
        }


        /// <summary>
        /// Operator to convert ClassObject - ToString
        /// </summary>
        /// <returns>#ID|#Login|#Pass|#NiceName|#Email data string</returns>
        public override string ToString()
        {
            return ID + "|" + Login + "|" + Pass + "|" + NiceName + "|" + Email;
        }
    }

LoginWPException:
Esta es una clase de gestión de excepciones que he generado, para controlar aquellos errores que sean derivados de la propia conexión con el WP. De esta forma, el código quedaría:

   public class LoginWPException : Exception
   {
        public LoginWPException(Exception e) : this(e.Message.ToString(), e) { }
        public LoginWPException(string message) : this(message, new Exception()) { }
        public LoginWPException(string message, Exception e) : base(message, e) { }
   }

LoginWPHelpers:
Esta clase contiene métodos auxiliares que se utilizan en la clase base o principal, y que he separado para un mejor control del código fuente. Dentro de esta clase, encontramos tres métodos:

1- ParseXmlData: Esta funcion tiene un parametro XmlDocument, que es convertido al modelo LoginUser. Se utiliza para transformar la información recibida desde la página 'wp-login-asp.php' del WP. Si detecta que existe un error (por la información que existe dentro del xml) lanza una WPException.

2- GetCookieContainer: Esta función, se encarga de almacenar las cookies actuales de la aplicación en un contenedor, convirtiendo las Web.HttpCookies a Net.Cookies, que se pueden utilizar en las llamadas WebHttpRequest.

NOTA: Aquí es dónde entra en juego la verificación de los usuarios registrados en el WP. Dado que tenemos la información compartida en cookies, si intentamos realizar una petición directa vía HttpWebRequest, el WP no será capaz de devolvernos ninguna información puesto que cada llamada es, por así decirlo, 'anónima'. Necesitamos enviar las cookies en un contenedor, y así, al recibirlas el archivo php, será capaz de gestionar la información y devolvernos al usuario registrado. (Esto me llevo bastante tiempo averiguarlo, y gracias al envío de las cookies, ambos sistemas pueden funcionar como uno sólo)

3- TransferCookieToApplication: De forma análoga a la anterior función, ésta se encarga de transferir las cookies recibidas desde la HttpWebRequest, a HttpCookies comprensibles por nuestra AppW.

El código fuente final de esta clase quedaría así:

 public class LoginWPHelpers
 {
  protected internal static LoginUser ParseXmlData(XmlDocument xmlDoc)
  {
   //el usuario es correcto, actualizamos la informacion
   LoginUser current = null;
   int valid = int.Parse(xmlDoc.SelectSingleNode("//object/is_valid").InnerText);
   //read XML and parse data
   if (valid < 1)
   {
    throw new LoginWPException(xmlDoc.SelectSingleNode("//object/error_message").InnerXml);
   }
   else
   {
    current = new LoginUser();
    current.ID = int.Parse(xmlDoc.SelectSingleNode("//object/id").InnerText);
    current.Login = xmlDoc.SelectSingleNode("//object/user_login").InnerText;
    current.Pass = xmlDoc.SelectSingleNode("//object/user_pass").InnerText;
    current.NiceName = xmlDoc.SelectSingleNode("//object/user_displayname").InnerText;
    current.Email = xmlDoc.SelectSingleNode("//object/user_email").InnerText;
   }
   return current;
  }


  protected internal static CookieContainer GetCookieContainer
    (HttpCookieCollection collection, string host)
  {
   CookieContainer cc = new CookieContainer();
   foreach (string cookie_name in collection)
   {
    HttpCookie cookie = collection[cookie_name];
    Cookie cCookie = new Cookie(cookie.Name, cookie.Value, cookie.Path);
    if (!String.IsNullOrEmpty(cookie.Domain))
     cCookie.Domain = cookie.Domain;
    else
     cCookie.Domain = "." + host;
    cCookie.Expires = cookie.Expires;
    cc.Add(cCookie);
   }
   return cc;
  }


  protected internal static void TransferCookieToApplication(Cookie c, string host)
  {
   //Write the wordpress cookie to the browser
   HttpCookie cCookie = new HttpCookie(c.Name);
   cCookie.Value = c.Value;
   cCookie.Expires = c.Expires;
   cCookie.Domain = "." + host;
   cCookie.Path = "/";


   HttpContext.Current.Response.Cookies.Add(cCookie);
  }
 }

LoginWPMethods:
Y aquí tenemos el 'alma mater' de nuestra aplicación... el corazón que hace que todo esto funcione. Veamos los métodos que están implementados en ella:

1- LoginToWordpress, LogoutToWordpress, LoggedStatusWordpress: Estas funciones son las encargadas de realizar la petición a la página .php y devolver la información del usuario registrado. En caso de no tener un usuario registrado, el propio sistema lanza una LoginWPException que debe ser correctamente gestionada. Cualquier otro error, se gestiona con una Exception normal. Cada una de las funciones envía el tipo de acción correspondiente, y los datos necesarios para ejecutar la acción.

Así, las tres funciones envían la url de acceso al php, y sólo LoginToWordpress envía los datos de usuario.

2- CallHttpWebRequest: Es la funcion privada que unifica las tres funciones públicas y se encarga de hacer la petición, obteniendo el Xml resultante.

3-GetXmlRequestData: Es la función que realiza el HttpWebRequest.

NOTA: Ésta última función tiene la particularidad (y diferencia con otros post que me sirvieron de guía) de que en vez de utilizar un CookieContainer vacio para enviar/recibir las cookies, genera uno propio con las cookies de nuestra aplicación. Es precisamente esta opción la que nos permite trabajar con ambas aplicaciones.

El código fuente final de esta clase quedaría así: 

 public class LoginWPMethods
  {
    public static LoginUser LoginToWordpress(string user, string pass, Uri url_loggin) {
      return CallHttpWebRequest("&Action=loggin&UserName=" + user + "&Pwd=" + pass, url_loggin);
    }
    public static void LogoutToWordpress(Uri url_loggin) {
      CallHttpWebRequest("&Action=logout", url_loggin);
    }
    public static LoginUser LoggedStatusWordpress(Uri url_loggin) {
      return CallHttpWebRequest("&Action=logged_status", url_loggin);
    }

    private static LoginUser CallHttpWebRequest(string data, Uri url_loggin)
    {
      LoginUser current = null;
      //TRY to get and parse data HttpWebRequest
      try
      {
        XmlDocument xmlDoc = GetXmlRequestData(data, url_loggin);
      current = LoginWPHelpers.ParseXmlData(xmlDoc);
      }
      catch (LoginWPException WPExc) { /* TODO - Error logic on WP access */ }
      catch (Exception exception) { throw exception; }
      finally {}
      return current;
    }

    private static XmlDocument GetXmlRequestData(string post_data, Uri url_loggin)
    {
      ASCIIEncoding encoding = new ASCIIEncoding();
      byte[] data = encoding.GetBytes(post_data);

      //Prepare web request...
      HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url_loggin);
      myRequest.Method = WebRequestMethods.Http.Get;
      myRequest.Method = "POST";
      myRequest.ContentType = "application/x-www-form-urlencoded";
      myRequest.ContentLength = data.Length;
      myRequest.CookieContainer = LoginWPHelpers.GetCookieContainer(
         HttpContext.Current.Request.Cookies, url_loggin.Host);
      Stream newStream = myRequest.GetRequestStream();

      //submit the php form for BuddyPress signup
      newStream.Write(data, 0, data.Length);
      newStream.Close();

      //Get the response, and pass it to a XML
      HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
      StreamReader reader = new StreamReader(myResponse.GetResponseStream());
      string string_reader = reader.ReadToEnd();

      //Look for cookies in the response
      if (myResponse.Cookies.Count > 0)
      foreach (Cookie c in myResponse.Cookies)
        LoginWPHelpers.TransferCookieToApplication(c, url_loggin.Host);

      //close response
      myResponse.Close();

      //parse XML Data
      XmlDocument xmlDoc = new XmlDocument();
      xmlDoc.LoadXml(string_reader);
      return xmlDoc;
    }
  }


Y con esto, tendríamos toda la lógica de gestión de usuarios para obtener un 'Single Sign On entre un WordPress y una Aplicación Web ASP.NET'.

FUNCIONES DE CONEXIÓN CON WP

Por último, y no menos importante, las funciones para el uso de todas estas funciones...

Una función para realizar el Login desde la aplicación Web:

 
    protected void Login_Click(object sender, EventArgs e)
    {
      try
      {
      //set loggin, create ticket if exist user AND STORE IN SESSION
      SessionHelper.CurrentUser = LoginWPMethods.LoginToWordpress(user_login.Text, user_pass.Text, new Uri(ConfigurationManager.AppSettings["PathWP"]));
      //esta funcion crea un ticket de FormsAuthentication para el acceso de usuarios
      LoginMethods.LogIn(SessionHelper.CurrentUser);
      Response.Redirect("~");
      }
      catch (Exception ee)
      {
      ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertLoggin", "MostrarAlerta('" + HttpUtility.JavaScriptStringEncode(ee.Message.ToString()) + "')", true);
      }
      finally { }
    }

Otra para desconectar o LogOut:
  public static void LogOut()
  {
      //eliminamos el ticket actual, y desconectamos del wordpress
      EliminarTicket();
      LoginWPMethods.LogoutToWordpress(new Uri(ConfigurationManager.AppSettings["PathWP"]));

      //borramos todo
      HttpContext.Current.Session.Clear();
      HttpContext.Current.Session.Abandon();
      HttpContext.Current.Request.Cookies.Clear();

      //redireccionamos al loginpage
      FormsAuthentication.RedirectToLoginPage();
  }

Y una función, LogginStatus, y que debe controlar las páginas que estén bajo registro (yo inserto esta función en una MasterPage, para controlar los accesos), que averiguará si existe un usuario registrado en WP o no.

Para evitar peticiones constantes al WP, dicha función sólo hace las llamadas si detecta que existen cookies de wp_loggin_id y el usuario actual no está autenticado en la AppW. De esta forma, sólo si hay un usuario WP y no AppW, se efectúa la llamada al php y obtenemos los datos del usuario para autenticarlo.

 
        public static LoginUser LogginStatus()
        {
            //set current user
            LoginUser current = null;
            //check if user is logged
            bool authenticated = HttpContext.Current.User.Identity.IsAuthenticated;
            //check if WP logged
            HttpCookie WP_Cookie = null;
            foreach (string c in HttpContext.Current.Request.Cookies)
                if (c.IndexOf("wordpress_logged_in_") != -1) WP_Cookie = HttpContext.Current.Request.Cookies[c];
            //VERIFICACIONES
            if (authenticated)
            {
                if (WP_Cookie == null && (HttpContext.Current.Request.Url.Host!="localhost")) LogOut(); //el usuario NO ESTÁ autenticado en WP, desconectamos
                else { current = GetUsuarioAutenticado(); }
            }
            else
            {
                if (WP_Cookie != null)
                {
                    //el usuario ESTÁ autenticado en WordPress. TOMAMOS LOS DATOS
                    current = LoginWPMethods.LoggedStatusWordpress(new Uri(ConfigurationManager.AppSettings["PathWP"]));
                    LogIn(current);
                }
            }
            return current;
        }


Y con esto ya hemos conseguido una integración total...
Os incluyo los enlaces a los otros post que hacen referencia al mismo tema:
· SSO ASP.NET to WordPress: Single Sign On
· SSO ASP.NET to WordPress: PHP Souce Code
Si os ha gustado y sobre todo, si os ha servido, no dudeis en valorarlo! +1
Un saludo a todos!
[...]

Leer más >>

SSO ASP.NET to WordPress: ASP.NET to Wordpress Single Sign On with HttpWebRequest

Hola a todos.

En este post, voy a tratar de explicar cómo se puede establecer un 'Single Sign On' (SSO) entre una aplicación web ASP.NET (AppW) y un WordPress (WP). El motivo que me ha llevado a compartir esta idea con todos vosotros, viene promovido por la escasa información completa que he encontrado en internet.

Aunque han sido numerosas las páginas que he encontrado con datos sobre cómo hacerlo, en ninguna explicaban el proceso completo y ,en la mayoría de los casos, sólo se centraban en la autenticación desde el lado de la aplicación AppW.

Debido a que el post es muy largo, lo he dividido en tres partes, y para no mezclar explicación con codigo podeís encontrar directamente los fuentes en los siguientes apartados:
· SSO ASP.NET to WordPress: PHP Souce Code
· SSO ASP.NET to WordPress: ASP.NET Souce Code

NOTA: En los ejemplos que encontré, la autenticación desde la aplicación AppW permitía al usuario trabajar desde el WP sin necesidad de registrarse de nuevo. Pero si la situación era la inversa, la aplicación web no detectaba que el usuario estaba registrado, y éste se tenía que autenticar de nuevo. En este post, os indico cómo poder lograr que ambos procesos funcionen como uno sólo.

PARA EMPEZAR, VAMOS A PONERNOS EN SITUACIÓN...


Lo que deseamos reproducir aquí, es un sistema de autenticación doble que permita a los usuarios registrarse en un WP o en la AppW, y poder alternar la navegación entre ambas sin que ello afecte al estado del login.

Nuestro objetivo es tener las cookies de autenticación bajo un mismo dominio, de forma que sean accesibles desde cualquier aplicación que esté en el mismo dominio. Por tanto, lo que tenemos que hacer es generar un sistema que genere las cookies que usa el WP y que nos permita gestionarlas desde la aplicación AppW.

El principal problema con el que nos encontramos al intentar registrarnos en alguna de las aplicaciones anteriores, es que las cookies que se generan en uno u otro sistema, no se pueden 'compartir' fácilmente entre ellas. De hecho, y por la privacidad preestablecida, esto no se puede hacer.... ¿o sí?

Condiciones Básicas para que todo funcione:
Las condiciones básicas que debemos tener para que el sistema que vamos a montar funcione, se podrían resumir en los siguientes puntos:
· Trabajar sobre un dominio propio, con acceso completo.
· Tener instalado un WP en ese dominio (o un subdominio)
· Tener una AppW instalada en ese dominio (o un subdominio)

Es muy importante que ambas aplicaciones corran bajo el mismo dominio, dado que de lo contrario, nunca podremos compartir las cookies entre ellas.

Supuestos iniciales:
Supongamos que tenemos toda la infraestructura montada, y que nuestras aplicaciones de ejemplo corren bajo el dominio de pruebas: http://mydomain.com
· el WP bajo wp.mydomain.com
· y la AppW bajo app.mydomain.com

Lo único que nos queda es generar las cookies bajo el dominio '.mydomain.com', y que sean por tanto, visibles desde ambas aplicaciones.

LÓGICA DE CLASES:

A partir de este punto, lo que vamos a ver es cómo debemos codificar los distintos elementos necesarios que nos van a permitir cumplir nuestro objetivo, el SSO.

Para ello, vamos a necesitar dos archivos que contendrán todo el código que necesitamos. Primero explicaré en qué consiste cada archivo, y luego veremos el código con algo más de profundidad.

1º Archivo PHP:
Este será el archivo que tendremos que subir al directorio raiz de nuestro WP, y que contendrá las sentencias necesarias para averiguar si: un usuario está conectado, si hay que desconectar a un usuario, o en qué estado se encuentra el wordpress (por si existe un usuario autenticado).

En el código de este archivo he incluido una función, que escribe la respuesta obtenida en formato XML. Aunque se podría establecer la salida de varias maneras, he preferido utilizar este formato porque facilita mucho la gestión posterior desde el lado .NET

De esta forma, el archivo final quedaría con la siguiente estructura:
- archivos de inclusión de WP
- código con la función para parsear la información obtenida
- sentencia swich, que puede tomar los valores "logged_status", "logout", y "loggin". Aquí es donde se encuentra la programación que realizará cada una de las acciones que serán solicitadas desde la AppW

2º Archivo de Clases .NET:
Este archivo de clases será el que contenga toda la lógica de conexión y autenticación entre nuestra AppW y nuestro WP. En principio lo he codificado todo en un único archivo para su mejor comprensión, aunque como bien sabéis, se debería haber realizado un archivo único por cada clase utilizada (principios básicos SOLID).

En este archivo, lo que encontraremos serán tres clases básicas y un modelo de datos:
· LoginUser: modelo que almacenará los datos devueltos por el WP y que se utiliza en la lógica de login de la AppW
· LoginWPMethods: clase principal con los métodos para conectar, desconectar o averiguar el estado del usuario en WP
· LoginWPException: clase para controlar las posibles excepciones que tengamos a la hora de autenticar usuarios
· LoginWPHelpers: clase con métodos auxiliares utilizados en la clase principal

IMPLEMENTACION:

Una vez generados los archivos, tendremos que realizar los siguientes pasos:

WORDPRESS
colgar en el directorio raiz del WP el archivo PHP.
activar el dominio para las cookies de forma que sean accesibles a todos los subominios. Esto se puede hacer, o bien instalando el plugin 'root Cookie' (puedes encontrarlo aqui), o bien pegando las siguientes líneas en el archivo wp-config.php:

define('LOGGED_IN_COOKIE', 'login_cookie_name');
define('AUTH_COOKIE','auth_cookie_name');
define('COOKIE_DOMAIN', '.example.com');
define('COOKIEHASH', 'random_hash_here');


APLICACIÓN WEB
Incluir el archivo de clases al proyecto, y añadir las referencias a la clase necesarias.
2º LOGIN:
· Para controlar el login del WP a AppW, debes incluir el código que llame a la función 'LoggedStatusWordpress' con la ruta del WP, y el objeto que te devolverá, te indicará si existe un usuario registrado o no.
· Para controlar el login en la AppW y actuar en consecuencia contra el WP, hay que llamar a la función 'LoginToWordpress'. El objeto devuelto indicará si el usuario introducido existe o no, y en caso correcto, realizará el login en el WP.
· Para desconectar, realizar la llamada a 'LogoutToWordpress', y el usuario será desconectado del WP
A partir de este punto, sólo quedaría implementar la lógica de acceso por autenticación de la applicación web, de forma que se mantengan autenticados a los usuarios mediante el formato <authentication mode="form" /> de .NET.


Debido a que el post es muy largo, y para no mezclar explicación con codigo, podeís encontrar directamente el código en este post en:

· SSO ASP.NET to WordPress: PHP Souce Code
· SSO ASP.NET to WordPress: ASP.NET Souce Code


Si os ha gustado y sobre todo, si os ha servido, no dudeis en valorarlo! +1

Un saludo a todos!
[...]

Leer más >>

Tincr: CSS and JAVASCRIPT browser extension

A aquellos de vosotros que, como desarrolladores, os guste tener multitud de plugins en los navegadores que faciliten vuestra labor, aquí os traigo un plugin que ha caido en mis manos y que he encontrado muy interesante.

Se trata de un plugin para editar las características CSS y JAVASCRIPT, directamente desde la consola del navegador Lamentablemente está solo disponible para Chrome, pero espero que algún día lo preparen para el resto de navegadores.

¿Y qué diferencia puede tener respecto a otros plugins similares, como Firebug, EditCSS, Web Developer Toolbar, etc? Pues, en principio, una bastante importante... Es capaz de guardar cada uno de nuestros cambios.

En la mayoria de las ocasiones, tenemos la necesidad de ir modificando multitud de elementos CSS en nuestras páginas, para ir viendo cómo va quedando el resultado final. El problema que nos encontramos entonces, es "pasar" todas las modificaciones realizadas a la página de estilo final.

Es entonces, cuando podemos perder alguna modificación porque no encontremos TODAS las actualizaciones que hemos realizado.

¿Y como viene Tin.cs a solucionar todos estos problemas?
Muy sencillo. Él solito se encarga de almacenar cada cambio que vamos haciendo, directamente en el archivo original del proyecto.

Por fin podemos realizar todos nuestros cambios y, al mismo tiempo que se ven reflejados en la página, se van almacenando en su página .css correspondiente. Ya no tenemos que buscar, copiar y pegar cada modificación que hemos efectuado.

PONIENDO EN MARCHA Tincr:
· INSTALACIÓN: Para poder empezar a utilizar Tincr, debemos descargarnos el plugin para Chrome (disponible aqui).
· CONFIGURACIÓN: Para configurar el plugin, debemos abrir la consola de desarrollador (Ctrl+Shift+i) y pulsar el botón de configuración de Tincr. En la ventana que se nos abre, seleccionamos el tipo de proyecto "Configuration File" y luego, indicamos la ruta a nuestro proyecto.
Sólo nos queda incluir en nuestro proyecto el archivo de configuración en donde le indicamos al plugin qué archivos debe controlar.
· INCLUSIÓN DEL ARCHIVO tincr.json: Dentro de la carpeta del proyecto, debemos incluir el archivo tincr.json (que utiliza el plugin), con el código fuente que indica dónde están nuestros archivos css y js, para que la gestión de los mismos se efectúe correctamente.

Aquí os pongo un ejemplo de cómo sería este archivo:

CÓDIGO JSON DE CONFIGURACIÓN:

{
       "toFile" : [
             {"from": "/js/(.+\\.js)",
              "to": "/js/$1"},
             {"from": "/css/(.+\\.css)",
              "to": "/css/$1"}
       ],
       "fromFile" : [
             {"from": "(\\\\|/)app\\1assets\\1(?:javascripts|stylesheets)\\1(.+(\\.js|\\.css))(\\.[a-zA-Z]+)?$",
              "to": "/assets/$2?body=1"}
       ]
}


Y YA ESTÁ:
Ya podemos empezar a utilizar la consola de desarrollador, y hacer cuantos cambios sean necesarios. Todos y cada uno de ellos, se almacenarán automáticamente en los archivos correspondientes.

Si tenéis abierto el programa con el que normalmente desarrolláis vuestras aplicaciones (Visual Studio en mi caso), podréis rechazar los cambios que el plugin haya realizado, simplemente con regresar a vuestro editor y cancelar el aviso que os indica que el archivo '...ha sido modificado fuera del editor...'.

Espero que os ayude en vuestros desarrollos, y os permita ganar tiempo a la hora de actualizar los diseños de vuestras aplicaciones.

Un saludo a todos!

REFERENCIAS:
Tincr site
Reference Docs
[...]

Leer más >>

Windows 8 Apps: Design Grid Layout Pattern

Ya he comenzado ha desarrollar algunas aplicaciones para el nuevo sistema operativo de Windows 8. Por supuesto, partiendo de toda la documentación de la que disponemos desde el MSDN Microsoft.

Uno de los primeros pasos que debemos seguir, pasa por construir nuestras aplicaciones siguiendo los consejos que nos ofrece. En concreto el diseño de la aplicación y el layout básico de cada elemento que vamos a incluir en nuestras páginas.

En este post, voy a tratar de resumir los conceptos básicos de distribución de elementos en el grid.

Y como a mi me gusta tener las cosas ordenaditas, he tratado de agrupar todas las dimensiones en un único documento. Para ello, he recogido todas las imágenes que MSDN pone a nuestra distribución y las he incluido en una sóla imágen. Así, podemos descargarla e imprimirla para tener toda la información de un sólo vistazo.



Estas son las directrices básicas:

TITULAR Y CONTENIDO
· Margen superior de 45 px para el titular de la aplicación (línea base del texto a 100 px).
· Margen superior del contenido de 140 px.
· Margen izquierdo de la aplicación a 120 px.

ELEMENTOS
· Espacio interno horizontal entre elementos de borde: 10 px.
· Espacio interno horizontal entre elementos de lista: 40 px.
· Espacio interno horizontal entre elementos de bloque/grupos: 80 px.

· Espacio interno vertical entre elementos de borde: 10 px.
· Espacio interno vertical entre elementos: 20 px.

FOOTER
· El margen del pie de la aplicación, puede variar en función de los contenidos, pero nunca debe ser mayor de 130 px ni menor de 50 px.

Aunque aquí están todos los márgenes establecidos en pixels, no está de más saber que se han obtenido a partir de la estructura básica que microsoft considera básica, en la cuadricula de trabajo. Para Windows8, la estructura básica es la unidad (20px), que contiene a su vez 16 subunidades (de 5 px cada una). Aquí os dejo la imágen gráfica que define todos estos conceptos.



Por supuesto, todas las imágenes pertenecen a Microsoft, y aquí lo único que he intentado es unificar y agrupar los conceptos.

Podéis encontrar toda la documentación e imágenes en la siguiente dirección http://msdn.microsoft.com/es-es/library/windows/apps/hh872191.aspx

REFERENCIAS:
MSDN Microsoft
Diseñar una página de aplicación
Tutorial para crear tu primera aplicación Windows 8
[...]

Leer más >>

CODE SNIPPET: Google Traking

Cuando la mayoría de los clientes te pide un proyecto, acaba solicitando también un completo estudio de visitas, páginas vistas, eventos, descargas, ect.

Google ofrece un gran abanico de posibilidades de gestión para dicha información. Si ya tienes una cuenta de Google, podrás acceder a este servicio. Sino, puedes generarte una y empezar a investigar en Google Analytics

En este CODE SNIPPET os voy a pasar un breve código javascript con el que fácilmente podremos incluir nuestras páginas en las estadísticas de Google, sin necesidad de copiar el mismo código en todas nuestras páginas.

Lo primero que debemos hacer es crear un archivo de texto en nuestro proyecto web, y luego, copiar y pegar el siguiente CÓDIGO JAVASCRIPT:

/* GLOBAL CONTROL VARS */
varANALYTICS_KEY = 'XXXXXXXXXXX';
varANALYTICS_DOMAIN = 'mydomain.com';

var_gaq = _gaq || [];
_gaq.push(['_setAccount', ANALYTICS_KEY]);
_gaq.push(['_setDomainName', ANALYTICS_DOMAIN]);
_gaq.push(['_trackPageview']);

/**
* Function to tracking google analitics
*/
(function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true;

    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(ga, s);

})();

/**
* Function to track events, width params
* @param {String} categoria Category to track.
* @param {String} accion    Event to track.
* @param {String} etiqueta  Label to set what is tracking.
* @param {String} valor     Optional: Aditional tracking data.
* @return {void}
*/
function TrackingLink(category, action, label, val) {
    if (!valor) {
        _gaq.push(['_trackEvent', category, action, label]);
    } else {
        _gaq.push(['_trackEvent', category, action, label, val]);
    }

Para actualizar dicho código en cada proyecto futuro, simplemente deberemos cambiar las variables ANALYTICS_KEY y ANALYTICS_DOMAIN, con los valores reales, y incluir una referencia al archivo js en cada página que deseemos trackear.


REGISTRO DE EVENTOS EN GOOGLE ANALYTICS:

En el código que os incluyo, veréis que existe una función encargada de insertar eventos en Google Analytics. Pues bien, esta función permite insertar y parametrizar, desde cualquier parte de la aplicación, un nuevo evento para su posterior análisis.

Aunque Google tiene bastante información al respecto, simplemente comentar que con esa función podemos controlar desde 'Clicks' hasta 'MouseOver', 'ExternalLinks', ect.

Si por ejemplo quisiéramos controlar el número de descargas realizadas en una página de descargas de nuestra aplicación, simplemente añadiendo el siguiente fragmento a cada enlace, tendríamos un control completo de esa información:

< a href="downloads/poster.zip" onclick="TrackingLink('Descargas'Click', 'Poster');">POSTER</a>
< a href="downloads/libro.zip" onclick="TrackingLink('Descargas', 'Click', 'Libro');">LIBRO</a>
< a href="downloads/juego.zip" onclick="TrackingLink('Descargas', 'Click', 'Game');">GAME</a>

o por ejemplo, el control de los enlaces a redes sociales:

<a href="http://tuenti.com/mituenti" onclick="TrackingLink('Redes', 'Click', 'Tuenti');">MI TUENTI</a>
<a href="http://facebook.com/micuentafacebook" onclick="TrackingLink('Redes', 'Click', 'Facebook');">MI FACEBOOK</a>

Ahora hay que dejar volar la imaginación!

REFERENCIAS:
Google Analytics
Traking Events Google
Cómo realizar un evento

Un saludo a todos.
[...]

Leer más >>