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.
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:
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:
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í:
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í:
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 {}
}
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;
}
}
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) { }
}
{
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);
}
}
{
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;
}
}
{
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 { }
}
{
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();
}
{
//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;
}
{
//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!
Do you have an example file?
ResponderEliminarSorry, but I can not publish the source code files. All lines of code in this post, are global implementations that anyone can use. The purpose of this post is to be a guide to development, for anyone to perform SSO implementations.
EliminarIf done step by step each and every one of the three examples, you will get the SSO smoothly. The first post is a general explanation, while the other two, spelling out how to program in ASP.NET and PHP environment respectively.
Regards
Hola Sr. Serrano
ResponderEliminarHe seguido su solución tan de cerca.
Es muy interesante. Actualmente estoy tratando de
para implementar su solución, pero lamentablemente
dos núcleos y métodos importantes faltan decisiones
la solución incompleta.
a - GetCookieContainer
b - TransferCookieToApplication
Sírvase volver a publicar esta solución o mejor aún
es posible que Bandeja de entrada (correo electrónico) me (jcc_nnannah@yahoo.co.uk)
con los archivos originales
Cuando pegarlos directamente en su blog que
gabbles cosas.
Usted ayudará mucho porque tengo
Ya pasó un tiempo considerable con este
Muchas gracias
Hi James,
EliminarI do not understand your mesaje, or its purpose. As I interpret, you're asking about the development of the two methods you write.
Such methods are under the heading 'LoginWPHelper', with all the source code needed for its operation.
If your question is another, you can ask about it in your native language.
Regards.
Hello Rafael
Eliminarsorry pls. I used the google translator. It obviously did a bad job.
I am very much interested in your solution and I followed it closely. But I could not find the declaration of two methods which was used later in the solution.
The important missing methods are
a - GetCookieContainer
b - TransferCookieToApplication
I do not know if it is the google translator that is messing up the files. When u copy from the blog and paste on the IDE it requires a lot of cleaning up with may introduce bugs
Please repost this solution or better yet you may inbox (email) me (jcc_nnannah @ yahoo.co.uk) with the original files.
It is quite interesting...
Thank you for your patience with me
James