Step1帐户登录系统(5.使用Yahoo BBAuth登录网站)
从系列之中的上一篇文章,我介绍了如何支持Windows Live ID来登录自己的网站,这一篇按照顺序,我介绍如何支持使用Yahoo BBAuth来登录网站,和上面的一篇文章一样,我将会仅仅对具体的逻辑进行实现,不再重复基础的原理。
关于Yahoo BBAuth的更多信息,请参考:Browser-Based Authentication。
可以先看Yahoo提供的BBAuth的原理示意图:

第一步当然也是到Yahoo! Developer Network Home去注册你的程序,注册界面大致是这样的:

在注册完成之后,就可以在My Projects之中看到如下的应用程序信息:

当然,Shared Secret需要点击链接才能看到,这里不得不要批评一下BBAuth的是,所有的信息注册之后没有看到什么地方可以修改,要改动一个什么(例如底下的访问数据列表),都需要重新注册一个应用程序,这样的设计似乎有点奇怪,还有一点,就是Yahoo提供的文档虽然不怎么样(我曾经因为一个时间格式问题被折磨了好久),各个范例和源码其实是很多的,只是不太好找,可能是我的英文功底不够吧。
好,闲话少说,在经过注册之后,得到了这样几个参数:appid,secret,这几个参数在程序之中需要使用的。
先看如何得到用来让用户登录的转向地址,这个非常容易,那几个参数也是现成的,只是格式是严格要求的,一定不能出错,否则反正Yahoo的BBAuth服务器反正就是给你出个错,让你摸不着头脑了,详细的代码还是在下面看看代码吧。
得到转向地址并转向给Yahoo之后,就可以将用户转向到Yahoo的公共登录界面,用户登录之后,就会出现关于登录许可的提示,用户只有点击同意才能继续登录的过程。

登录完成之后,就开始Yahoo的服务器的就开始回转到你的Web应用程序,回传之后,根据请求的参数,需要按顺序完成以下步骤:
1.检查回传得Token是否正常;
2.根据回传的Token向Yahoo的服务器请求WSSID;
3.根据WSSID向Ymail接口请求用户的E-mail地址;
得到E-mail地址之后,就完成了整个登录过程。
下面是实现过程的代码:
1
public class BBAuthServer:BaseServer2

{3
private string appid, secret, server, pathLogin, pathPwtoken_login;4
private int timeout=300;5
//采用Web.Config之中的XML节点作为构造函数参数6
public BBAuthServer(System.Xml.XmlNode node)7
: base(node)8

{9
for (int i = 0; i < node.Attributes.Count; i++)10

{11
switch (node.Attributes[i].LocalName)12

{13
case "appid":14
appid = node.Attributes[i].Value;15
break;16
case "secret":17
secret = node.Attributes[i].Value;18
break;19
case "server":20
server = node.Attributes[i].Value;21
break;22
case "pathLogin":23
pathLogin = node.Attributes[i].Value;24
break;25
case "pathPwtoken_login":26
pathPwtoken_login = node.Attributes[i].Value;27
break;28
case "timeout":29
timeout = int.Parse(node.Attributes[i].Value);30
break;31
}32
}33
}34
public bool checkRequest(HttpRequest Request)35

{36
string ts = Request["ts"];37
string sig = Request["sig"];38
//先检查时间39
if (Math.Abs(long.Parse(ts) - ((long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds))) > timeout)40

{41
// throw new Exception("Error parsing timeout.");42
}43
//再检查签名44
string baseString = System.Text.RegularExpressions.Regex.Replace(Request.Url.PathAndQuery, "&sig=[^&]+", "");45
if (System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(baseString + secret, "MD5").ToLower() != sig)46

{47
throw new Exception("Signature mismatch:" + baseString);48
}49
return true;50
}51
public string getWSSID(string token,out string cookie)52

{53
string ts = ((long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds)).ToString();54
string baseString = pathPwtoken_login+"appid=" + HttpUtility.UrlEncode(appid) + "&token=" + HttpUtility.UrlEncode(token) + "&ts=" + ts + "";55
string sig = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(baseString + secret, "MD5").ToLower();56
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(server + baseString + "&sig=" + sig));57
request.Method = "GET";58
HttpWebResponse response = (HttpWebResponse)request.GetResponse();59
XmlDocument doc = new XmlDocument();60
doc.Load(response.GetResponseStream());61
cookie = doc.SelectSingleNode("//*[local-name()='Cookie']").InnerText.Trim().Substring(2);62
return doc.SelectSingleNode("//*[local-name()='WSSID']").InnerText.Trim();63
}64
public string getUserName(string token,string wssid,string cookie)65

{66
try67

{68
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("http://mail.yahooapis.com/ws/mail/v1.1/soap?appid=" + HttpUtility.UrlEncode(appid) + "&WSSID=" + HttpUtility.UrlEncode(wssid)));69
request.Method = "POST";70
request.CookieContainer = new System.Net.CookieContainer();71
CookieCollection collection = new CookieCollection();72
request.CookieContainer.Add(new Uri("http://mail.yahooapis.com/"), new Cookie("Y", cookie));73
byte[] bytes = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><SOAP-ENV:Body><GetUserData xmlns=\"urn:yahoo:ymws\"></GetUserData></SOAP-ENV:Body></SOAP-ENV:Envelope>");74
request.Headers.Add("SOAPAction", "\"\"");75
request.ContentType = "application/soap+xml; charset=utf-8";76
request.ContentLength = bytes.Length;77
Stream rs = request.GetRequestStream();78
rs.Write(bytes, 0, bytes.Length);79
rs.Close();80
HttpWebResponse response = getResponse(request);81
XmlDocument doc = new XmlDocument();82
doc.Load(response.GetResponseStream());83
return doc.SelectSingleNode("//*[local-name()='defaultID']").InnerText;84

/**//*85
ymws ymwsInstance = new ymws();86
ymwsInstance.Url = "http://mail.yahooapis.com/ws/mail/v1.1/soap?appid=" + appid + "&wssid=" + wssid;87
ymwsInstance.CookieContainer = new System.Net.CookieContainer();88
CookieCollection collection = new CookieCollection();89
ymwsInstance.CookieContainer.Add(new Uri("http://mail.yahooapis.com/"), new Cookie("Y", cookie));90
GetUserDataResponse userData = ymwsInstance.GetUserData(new GetUserData());91
return userData.data.userSendPref.defaultID;*/92
}93
catch (Exception)94

{95
return wssid;96
}97
}98
public override string getLoginUrl()//生成登录的URL99

{100
string ts = ((long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds)).ToString();101
string baseString = pathLogin+"appid=" + HttpUtility.UrlEncode(appid) + "&appdata=" + HttpUtility.UrlEncode(name) + "&send_userhash=1&ts=" + ts + "";102
string sig = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(baseString + secret, "MD5").ToLower();103
return server + baseString + "&sig=" + sig;104
}105
public override void parseHandle(HttpContext page)//处理回转请求106

{107
checkRequest(page.Request);//检查回传请求是不是合法108
string cookie;109
string wssid = getWSSID(page.Request["token"],out cookie);//先获取wssid110
string name = getUserName(page.Request["token"], wssid, cookie);//通过wssid获取用户名111
//检查完毕,开始获得用户的WSSID112
AccountHelper.setUserInfo(page.Request["userhash"], name, this.name);113
AccountHelper.returnOpener();114
page.Response.End();115
}116
public static HttpWebResponse getResponse(HttpWebRequest request)117

{118
try119

{120
return (HttpWebResponse)request.GetResponse();121
}122
catch (WebException e)123

{124
HttpContext.Current.Response.Write(e.Message);125
string result = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();126
HttpContext.Current.Response.Write(result);127
HttpContext.Current.Response.End();128
}129
return null;130
}131
}
posted on 2008-12-01 22:15 K_Reverter 阅读(1174) 评论(0) 收藏 举报
浙公网安备 33010602011771号