跨域登录是一个比较烦人的事情,往往我们需要写文章记录下来,或者探讨,或者抛砖引玉的问题,都是令人头疼的。上次简单得写了一篇关于跨域登录的文章,只讲了大体的实现过程。但是现在碰到了更大的问题,这篇文章将会介绍这个成败,并探讨、实现新方案的可行性。
跨域登录需要一张通行证,也可以称之为票据。就老衲现在知道和实验的方式一共有三种:
1、浏览器get参数;
2、session
3、cookie
每个都有特定的条件,以及需要处理的细节,也会带来一些新问题。根据经验,浏览器带参数,将会使系统开发得不像个东西,至少我是这么认为的。需要考虑对这个地址参数处理的各种策略,一开始我就否定了这个方案。在我需要改造的项目中有4个独立域名,跳转来跳转去,将会给用户造成极为不爽的体验。
session也可以解决问题,但是有一个问题无法解决。
先看看怎么用session解决问题。假设现在有a.com,b.com,现在开两个子域名: passport.a.com和passport.b.com。然后把这两个域名指向同一个站点,也就是在同一个站点的http投绑定这两个域名。
那么登录的时候,在 passport.a.com上登录成功,就可以设置一个session,那么在两个系统当中都是可以通过代理文件,访问到这个session的,这个方案确实是可行的。但是session只能保持20分钟,新问题就出来了。假设这个用户20分钟没有去操作,而打开了另外一个域名,那么这个判断就失效了。访问本域是没问题的,cookie还在那里摆着。
我比较倾向于用cookie来解决问题。上一次设计的系统,可以说极其简单。4个系统,有3个是asp.net的,还有个论坛是asp的(不用说就是动网的了)。现在就有四套登录系统。如果整体上全部改造,老衲认为成本太大了。后来四处逛网站,借鉴了Sohu的登录方式,但是只做了个体验的实现,如果全部实现了就不会现在在这里探讨这个问题了。解决方案就是javascript + iframe实现的。
本来想用纯javascript实现,然后给src的文件带参数,但是实际开发过程中,应该是我的js水平太菜,所以感觉不到想要的那种效果。后来就采用了javascript + iframe的方式来实现。是无刷新的那种哦,呵呵。
// JavaScript Document
//<script type="text/javascript" language="javascript">
function $P(id)
{
return document.getElementById(id);
}
function HJ_Passport(domain)
{
/*private*/
var me = this;
var version = "1.1";
var author = "yurow";
var iframe = "<iframe id=\"passport_frm_1\" style=\"display:none\"></iframe>";
var uicode = "<div id=\"passport_login\"><p>请输入帐号和密码</p><span id=\"passport_login_user\">用户:<input id=\"passport_username\" type=\"text\"></span><span id=\"passport_login_pass\">密码:<input id=\"passport_password\" type=\"password\"></span><div id=\"passport_login_action\"><button οnclick=\"hj_passport.OnSign();\">登陆</button><button οnclick=\"hj_passport.UICode.Hide();\">取消</button></div></div>";
var _id;
var _g;
var intervalId = 0;
var sites = [["site1","www.a.com","SetLogin.aspx","SetLogout.aspx"],["site2","www.b.com","SetLogin.asp","SetLogout.asp"]];
/*public*/
this.passport = "http://passport.c.com/";
this.passport_ui_id = "passport_ui";
this.UserName = "";
/*private set or get*/
HJ_Passport.prototype =
{
Author:author,
Version:version
}
this.UICode={
UICode:uicode
}
this.UICode.Set = function(code){
uicode = code;
}
this.UICode.Draw = function(){
document.write(iframe + "<div id=\"" + me.passport_ui_id + "\"></div>");
}
this.UICode.Show = function(){
var pobj = $P(me.passport_ui_id);
if(pobj== null){
me.UICode.Draw();
me.UICode.Show();
}else{
pobj.innerHTML = uicode;
pobj.style.display = "";
}
}
this.UICode.Hide = function()
{
var pobj = $P(me.passport_ui_id);
if(pobj!= null){
pobj.style.display = "none";
}
};
this.State =
{
ID : function(){ return _id; },
G : function(){ return _g; }
}
this.State.Set = function(id,g){
_id = id;
_g = g;
}
var Checked = function()
{
// alert($P("passport_frm_1").readyStatus);
// if($P("passport_frm_1").readyState == "complete")
// {
// alert("登陆成功!");
// clearInterval(intervalId);
// }
}
var ObServerLocation = function()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#')){
hash = hash.substring(1);
if(hash.indexOf("e_usr") > -1 || hash.indexOf("e_pss") > -1)
{
var err = "";
if(hash.indexOf("e_usr")> -1)
err += "用户名不能为空!";
if(hash.indexOf("e_pss")> -1)
err += "密码不能为空!";
clearInterval(intervalId);
alert(err);
}
else{
if(hash.length < 5 || hash == '0|'){
clearInterval(intervalId);
alert("用户名或者密码错误,登陆失败!");
}
else
{
var sp = hash.split('|');
if(sp.length == 3 && sp[0].length == 36 && !isNaN(sp[1]))
{
clearInterval(intervalId);
// if(encodeURI(me.UserName).toLowerCase() != sp[2].toLowerCase()){
// me.UserName = "";
// alert("登陆失败!");
// }
// else{
me.State.Set(sp[1],sp[0]);
//alert("登陆成功!")
var url = me.passport + "setlogin.aspx?g=" + me.State.G() + "&id=" + me.State.ID();
$P("passport_frm_1").src = url;
//intervalId = setInterval(Checked,5000);
//fn.call();
var s = new String(location.href);
location.href = s.substring(0,s.indexOf("#")) + "#";
try{
if(OnSignEnd)OnSignEnd();
}catch(e){}
// }
}
}
}
//clearInterval(intervalId);
}
}
this.OnSign = function(){
var username = $P("passport_username").value;
var password = $P("passport_password").value;
me.UserName = username;
var url = me.passport + "jslogin.aspx?username=" + escape(username) + "&password=" + escape(password) + "&r=" + Math.random();
$P("passport_frm_1").src = url;
intervalId = setInterval(ObServerLocation, 500);
}
var ObServerLogout = function()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#')){
hash = hash.substring(1);
if(hash == "0|")
{
clearInterval(intervalId);
var url = me.passport + "setlogout.aspx?r=" + Math.random();
$P("passport_frm_1").src = url;
try{
if(OnSignOutEnd)OnSignOutEnd();
}catch(e){}
}
}
}
this.OnSignOut = function(){
var url = me.passport + "jslogout.aspx?r=" + Math.random();
$P("passport_frm_1").src = url;
intervalId = setInterval(ObServerLogout,500);
};
}
//</script>
Response.AddHeader("P3P", @"CP=""CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR""");
Response.AddHeader("Content-Encoding:", "utf-8");
string url = Request.ServerVariables["HTTP_REFERER"];
if (!string.IsNullOrEmpty(url) && url.IndexOf('#') > 0)
{
url = url.Substring(0, url.IndexOf('#'));
}
string username = Request["username"];
string password = Request["password"];
Response.Write("<script>var f=parent;/*alert(f.document);*/f.location.href = '" + url + "' + '#' + ");
bool error = false;
if (string.IsNullOrEmpty(username))
{
Response.Write("'e_usr");
error = true;
}
if (string.IsNullOrEmpty(password))
{
if (error)
Response.Write("|");
else
Response.Write("'");
Response.Write("e_pss");
error = true;
}
if (error)
{
Response.Write("';</script>");
Response.End();
}
password = HttpUtility.UrlDecode(password, System.Text.Encoding.UTF8);
password = EncryptHelper.MD5(password);
password = password.Substring(8, 16);
BBSUser bu = BBSUserHelper.Current(username, password);
if (bu.UserID != 0)
{
DateTime dt = DateTime.Now;
string save = RequestHelper.Get("save");
//dt = string.IsNullOrEmpty(save) ? dt.AddHours(2) : dt.AddMonths(1);
dt = dt.AddMonths(1);
Guid g = Guid.NewGuid();
StatUserHelper.Delete(bu.UserID);
StatUser su = new StatUser();
su.UserID = bu.UserID;
su.UserName = bu.UserName;
su.ExpireTime = dt;
su.CreateTime = DateTime.Now;
su.Guid = g;
su.Password = bu.Password;
su.ID = StatUserHelper.Add(su);
string cachedate = su.Guid.ToString() + "|" + su.ID;
string cacheuser = bu.UserID + "|" + bu.UserName;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, cachedate, DateTime.Now, dt, true, cacheuser);
string authTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, authTicket);
UserCookie.Domain = ".c.com";
UserCookie.Expires = ticket.Expiration;
if (Response.Cookies[FormsAuthentication.FormsCookieName] == null)
Response.Cookies.Add(UserCookie);
else
Response.Cookies.Set(UserCookie);
Response.Write("'" + cachedate + "|" + HttpUtility.UrlEncode(bu.UserName, Encoding.UTF8) + "';</script>");
Response.End();
}
Response.Write("'0|';</script>");
Response.End();