Step1帐户登录系统(2.基础代码)
在前面的文章之中,我介绍了一下Step1帐户登录系统的基本编程架构,而在这篇文章,将直接贴出相关的源码,由于这次的开发比较仓促,代码存在很多不完善的地方,因此,适合仅仅用来作为如何实现的代码,而不是适合直接使用,废话少说,直接看代码:
首先是登录页面的代码,代码分为代码文件和页面文件两个部分:
1
public partial class LoginPage : System.Web.UI.Page 2

{3
public string url,returnUrl=null;4
public System.Collections.Specialized.NameValueCollection userInfo=null;5
protected void Page_Load(object sender, EventArgs e)6

{7
url = Request.QueryString["url"];//获得登录完成后回转的URL8
if (url == null || url.Length <= 0)9

{10
if (Request.UrlReferrer != null)11

{12
url = Request.UrlReferrer.ToString();13
}14
}15
userInfo=AccountHelper.getUserInfo();//获得当前已经登录的用户信息16
if (userInfo != null && url != null && url.Length > 1)17

{18
returnUrl = AccountHelper.getReturnUrl(url);//如果已经登陆,则直接将回转地址显示在页面的连接上19
}20
BaseServer server = AccountHelper.getServerByName(Request["ass"]);//如果通过ass参数指定了登录的类型(用户已经点击图标登录)21
if (server != null)22

{23
if (url != null && url.Length > 0)24

{25
AccountHelper.saveUrl(url);//将登录回转的地址记录到Cookie26
}27
Response.Redirect(server.getLoginUrl(),true);//转向到相应的登录页面28
}29
}30
}
下面是登录页面的页面文件,实际上就是显示登录界面的HTML内容:
1

<%
@ Page Language="C#" AutoEventWireup="true" Inherits="Step1.AccountServer.LoginPage"%><html>2
<head>3
<title>Step1.cn账户登录系统</title>4
</head>5
<body>6
<table>7
<tr><td class="icon">8
<a href='?ass=live.com&url=<%=HttpUtility.UrlEncode(url, System.Text.Encoding.Default)%>'><img src="icons/live.gif"/></a>9
</td><td class="icon">10
<a href='?ass=google.com&url=<%=HttpUtility.UrlEncode(url, System.Text.Encoding.Default)%>'><img src="icons/google.gif" class="icon"/></a>11
</td><td class="icon">12
<a href='?ass=yahoo.com&url=<%=HttpUtility.UrlEncode(url, System.Text.Encoding.Default)%>'><img src="icons/yahoo.gif" class="icon"/></a>13
</td><td class="icon">14
<a href='?ass=xiaonei.com&url=<%=HttpUtility.UrlEncode(url, System.Text.Encoding.Default)%>'><img src="icons/xiaonei.gif" class="icon"/></a>15
</td></tr>16
<tr><td class="desc">17
<b>Live</b>,<b>MSN</b>,<b>Hotmail</b>用户18
</td><td class="desc">19
<b>Google</b>,<b>Gmail</b>用户20
</td><td class="desc">21
<b>Yahoo</b>,<b>Flickr</b>用户22
</td><td class="desc">23
<b>校内网</b>用户(即将推出)24
</td></tr>25
</table>26

<%
if(userInfo!=null){%>27
<div class="user">28
<b><%=userInfo["name"]%></b> ,您好!您已经使用 <%=userInfo["type"]%> 账号登录29

<%
if(returnUrl!=null) {%><a href="<%=returnUrl %>">点击返回</a><%
} %>30
</div>31
<%}%>32
<div class="notice">说明:</div>33
</body>34
</html>
上可以看出,服务端支持哪几种登录方式和登录界面完全没有关系,前台登录界面并不是自动生成的。
然后是注销的Logout.aspx代码,注销的代码因为没有界面,因此没有页面文件(空文件),仅仅有一个代码文件:
1 public partial class LogoutPage : System.Web.UI.Page
2 {
3 protected void Page_Load(object sender, EventArgs e)
4 {
5 //退出系统,如果URL不存在,则返回登录页
6 string url = Request.QueryString["url"];
7 if (url == null || url.Length <= 0)
8 {
9 url = Request.UrlReferrer.ToString();
10 }
11 AccountHelper.clearCookie();//清除用户的Cookie
12 AccountHelper.redirect(url);
13 }
14 }
注销的代码要简单得多,不过不是最简单的,最简单的是Handler.aspx,这个文件之所以简单是因为同样没有页面文件,再加上其中的代码文件所做的事情都已经调用其它的类来完成,因此只有一个非常简单的代码文件:
1
public partial class HandlePage : System.Web.UI.Page 2


{3
protected void Page_Load(object sender, EventArgs e)4

{5
BaseServer server = AccountHelper.getServerByName(Request["ass"]);//根据ASS参数找到对应的服务器类型对象6
server.parseHandle(this.Context);//由该对象来处理返回请求7
}8
});
在上面的三个aspx文件的代码之中,无一例外的调用了AccountHelper类,这个类包含一些重要的静态方法,内容如下:
1
public class AccountHelper2

{3
//清除Cookie4
public static void clearCookie()5

{6
HttpCookie loginCookie = new HttpCookie(Configuration.Instance().cookieName);7
loginCookie.Expires = DateTime.Now.AddYears(-10);8
loginCookie.Domain = Configuration.Instance().cookieDomain;9
loginCookie.HttpOnly = false;10
HttpContext.Current.Response.Cookies.Add(loginCookie);11
}12
//将用户信息加入到Cookie13
public static void setUserInfo(string account, string name, string type)14

{15
HttpCookie loginCookie = new HttpCookie(Configuration.Instance().cookieName);16
loginCookie.Domain = Configuration.Instance().cookieDomain;17
loginCookie.Values.Add("account", Convert.ToBase64String(Encoding.UTF8.GetBytes(account)));18
loginCookie.Values.Add("name", Convert.ToBase64String(Encoding.UTF8.GetBytes(name)));19
loginCookie.Values.Add("type", Convert.ToBase64String(Encoding.UTF8.GetBytes(type)));20
loginCookie.Expires = DateTime.Now.AddYears(1);21
HttpContext.Current.Response.Cookies.Add(loginCookie);22
}23
//从Cookie之中获取用户信息24
public static NameValueCollection getUserInfo()25

{26
HttpCookie cookie = HttpContext.Current.Request.Cookies[Configuration.Instance().cookieName];27
if (cookie != null)28

{29
NameValueCollection userInfo = new NameValueCollection();30
foreach (string key in cookie.Values)31

{32
userInfo.Add(key,Encoding.UTF8.GetString(Convert.FromBase64String(cookie.Values[key])));33
}34
return userInfo.HasKeys()?userInfo:null;35
}36
return null;37
}38
//保存URL以便在完成后转向39
public static void saveUrl(string url)40

{41
HttpCookie loginCookie = new HttpCookie(Configuration.Instance().cookieName + "_url");42
loginCookie.Value = url;43
loginCookie.Domain=Configuration.Instance().cookieDomain;44
loginCookie.Expires = DateTime.Now.AddDays(1);45
HttpContext.Current.Response.Cookies.Add(loginCookie);46
}47
//将用户的登录参数加入到URL并回转给Web应用48
public static void returnOpener()49

{50
HttpCookie urlCookie = HttpContext.Current.Request.Cookies[Configuration.Instance().cookieName + "_url"];51
string url = getReturnUrl(urlCookie == null ? "./" : urlCookie.Value);52
urlCookie.Expires = DateTime.Now.AddYears(-10);53
HttpContext.Current.Response.Cookies.Add(urlCookie);54
redirect(url);55
}56
//根据已登陆用户信息和回转的基础URL地址得到回转的URL57
public static string getReturnUrl(string url)58

{59
url += (url.IndexOf("?") > 0) ? "&" : "?";60
System.Collections.Specialized.NameValueCollection userInfo = HttpContext.Current.Request.Cookies[Configuration.Instance().cookieName].Values;61
string[] infoArr = new string[userInfo.AllKeys.Length];62
userInfo.CopyTo(infoArr, 0);63
url += Configuration.Instance().paramName + "=" + HttpContext.Current.Server.UrlEncode(string.Join(",", userInfo.AllKeys) + ";" + string.Join(",", infoArr));64
return url;65
}66
//转向到指定URL,否则转向到登录页67
public static void redirect(string url)68

{69
if (url == null || url.Length <= 0)70

{71
HttpContext.Current.Response.Redirect("Login.aspx");72
}73
else74

{75
HttpContext.Current.Response.Redirect(url);76
}77
}78
//根据帐户类型的名称返回对应的帐户服务对象79
public static BaseServer getServerByName(string name)80

{81

if (name == null || name.Length < 1)
{ return null; }82
BaseServer[] servers=Configuration.Instance().AccountServers;83
for (int i = 0; i < servers.Length; i++)84

{85
if (servers[i].name == name)86

{87
return servers[i];88
}89
}90
return null;91
}92
public static string getHandleUrl()93

{94
return Configuration.Instance().rootUrl + "Handler.aspx";95
}96
public static string getLoginUrl()97

{98
return Configuration.Instance().rootUrl + "Login.aspx";99
}100
}
上面的代码就是比较长的一段了,不过确实是比较重要的一些方法,而下面的BaseServer.cs是一个抽象类,所有的登录类型(例如Google AuthSub类型,Yahoo BBAuth类型)都继承自此类,此类本身不能实例化:
1
public abstract class BaseServer2

{3
public string name;4
public BaseServer(System.Xml.XmlNode node)5

{6
for (int i = 0; i < node.Attributes.Count; i++)7

{8
switch (node.Attributes[i].LocalName)9

{10
case "name":11
name = node.Attributes[i].Value;12
break;13
}14
}15
}16
public virtual string getLoginUrl()17

{18
return "";19
}20
public virtual void parseHandle(HttpContext page)21

{22
}23
public virtual string getHandleUrl()24

{25
return AccountHelper.getHandleUrl()+"?ass=" + name;26
}27
}
到这里,这些基础的类就都介绍完毕,我之所以不厌其烦的将这些代码都贴上来,主要是为后面介绍每一种登录类型的时候,能够比较清晰的看出是登录过程如何实现的,上面的代码都比较简单,因为都是本站自己的逻辑,但是当涉及到和Google、Yahoo等的帐户服务器交互的时候,很多时候必须完全按照对应的接口来做,因此会比较难懂。
posted on 2008-11-24 20:59 K_Reverter 阅读(966) 评论(1) 收藏 举报
浙公网安备 33010602011771号