Step1帐户登录系统(3.使用Google的Auth Sub登录网站)

        前面的文章之中,我介绍了Step1帐户登录系统基本实现架构代码,从这一篇开始,我开始逐次讲解各种帐户的登录过程,在文章的最后,我都会贴出相应的代码,在代码之中有很多调用了前一篇文章之中讲到的基础代码,因此,可能需要对照才能明白。

        先从Google的AuthSub开始讲起,为什么呢,因为AuthSub最简单,实现起来很容易,记得我开始焦头烂额的研究了一个多星期Google的OAuth,始终没有成功,可是当我改成调用AuthSub之后,几个小时就实现了整个登录过程。

        有关Google AuthSub的文档和相关的内容,请参考:AuthSub Authentication for Web Applications

        废话少说,现直接看一个Google的AuthSub登陆过程介绍图片:

        从以上的流程图可以看出,实际上的登录至需要做以下几件事情:

        1.生成用来转向给Google认证系统的网址并转向(图中1);

        2.接受从Google认证系统回转的页面参数(图中4)

        3.使用Google的返回的参数向Google请求用户信息(图中5和6)

        现在,让我们来按照顺序完成以上流程:

        首先,你的程序必须在Google注册才能调用此接口,因此先到Google的Manage your domains 页面注册你的程序,注册界面如下:

        需要注意以下几点:

        1."Target URL path prefix"只是个前缀而已,并不是完整的回转的路径,在生成登录的时候,还是要将回转的路径发送给Google,而且必须和这里注册的前缀相符,这应该算是用来保障安全的一个设置。

        2.OAuth Consumer Key和OAuth Consumer Secret在OAuth认证的时候相当的重要,不过在AuthSub之中是没有用到的。

        注册完成之后,就要开始生成登录的URL,按照Google的文档,AuthSub的登陆URL应该是https://www.google.com/accounts/AuthSubRequest 加上一些参数组成,我用到了两个参数:

        1.next参数,指定用户登录完成之后回转的URL地址,注意必须以上面注册的"Target URL path prefix"开头;

        2.scope参数,指定需要访问哪些资源,这里的资源是以URL来描述的,例如我们在系统之中需要得到用户的登录用户名,所以要访问用户的通讯录(Google登录回转参数并不包含用户名),因此可以从Google Contacts Data API 上查到需要使用的scope为http://www.google.com/m8/feeds/,注意,如果需要访问多个资源,则以空格隔开每个URL

    结合以上两个参数(注意,每一个参数都必须经过URL编码),就可以的到一个URL地址,例如https://www.google.com/accounts/AuthSubRequest?next=http%3a%2f%2faccount.step1.cn%2faccount%2fHandler.aspx%3fass%3dgoogle.com&scope=http%3a%2f%2fwww.google.com%2fm8%2ffeeds%2f,我们将用户转向过去,用户就会到达Google的登陆界面(假如用户已经登录到Google,则会跳过此界面):

        用户登录之后,就会到Google的帐户信息授权页面,询问用户是否授权系统访问用户的特定信息:

        用户只有点击“授予访问权”才会正常登录,在登录完成之后,Google会将用户转向到访问你在上面的next参数之中指定的URL地址,并在地址之中加入一个token参数包含一个访问令牌,例如这个网址:http://account.step1.cn/account/Handler.aspx?ass=google.com&token=CJaHiYeKEBCE7qWi-v____8B

        我们只需要在回转页面(我系统之中的Hander.aspx)之中对token参数进行处理即可,需要说明的是,我不愿意为每一种登录类型都建立一个回转页面,这样会带来维护上的麻烦,因此我的所有回转页面都是Handler.aspx然后通过ass参数进行区分。

        下一步就是根据我们已经得到的token参数获取用户的用户名(E-mail地址),我研究了好久,最后发现发现只需要访问用户的地址本即可,因为用户即使地址本之中没有任何内容,返回的内容也包含他本人的E-mail地址,因此,我通过HttpWebRequest访问如下网址:http://www.google.com/m8/feeds/contacts/default/thin?max-results=0

,这个大体含义是以最简单的结果(thin)返回地址本之中的0条记录,当然,访问的时候要使用刚才获取到的token令牌,否则会得到需要认证的提示,具体的方法请参考下面的代码。

        最后,将得到的用户名和用户昵称保存到Cookie,大功告成!

        以下是我实现的以上过程的类AuthSubServer.cs的源码:

 

ContractedBlock.gif ExpandedBlockStart.gif AuthSubServer.cs的源码
 1    public class AuthSubServer:BaseServer
 2ExpandedBlockStart.gifContractedBlock.gif    {
 3        private string urlAuthSubRequest, urlScope, urlData;
 4        //采用Web.Config之中的XML节点作为构造函数参数
 5        public AuthSubServer(System.Xml.XmlNode node)
 6            : base(node)
 7ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 8            for (int i = 0; i < node.Attributes.Count; i++)
 9ExpandedSubBlockStart.gifContractedSubBlock.gif            {
10                switch (node.Attributes[i].LocalName)
11ExpandedSubBlockStart.gifContractedSubBlock.gif                {
12                    case "urlAuthSubRequest":
13                        urlAuthSubRequest = node.Attributes[i].Value;
14                        break;
15                    case "urlScope":
16                        urlScope = node.Attributes[i].Value;
17                        break;
18                    case "urlData":
19                        urlData = node.Attributes[i].Value;
20                        break;
21                }

22            }

23        }

24        public override string getLoginUrl()//生成登录的URL
25ExpandedSubBlockStart.gifContractedSubBlock.gif        {
26            return urlAuthSubRequest + "next=" + HttpUtility.UrlEncode(getHandleUrl()) + "&scope=" + HttpUtility.UrlEncode(urlScope);
27        }

28        public override void parseHandle(HttpContext page)//处理回转请求
29ExpandedSubBlockStart.gifContractedSubBlock.gif        {
30            string token = page.Request["token"];
31            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(urlData));//访问通讯录数据
32            request.Headers.Add("Authorization""AuthSub token=\"" + token + "\"");//这一句将token令牌加入到数据访问请求之中
33            request.Method = "GET";
34            HttpWebResponse response = (HttpWebResponse)getResponse(request);
35            XmlDocument doc = new XmlDocument();
36            if (response != null)
37ExpandedSubBlockStart.gifContractedSubBlock.gif            {
38                doc.Load(response.GetResponseStream());
39                XmlNode node = doc.SelectSingleNode("*/*[local-name()='id']");//读取用户的ID(E-mail地址)
40                string account = node != null ? node.InnerText : "";
41                node = doc.SelectSingleNode("*/*[local-name()='author']/*[local-name()='name']");//读取用户昵称
42                string name = node != null ? node.InnerText : "";
43                AccountHelper.setUserInfo(account, name, this.name);
44                AccountHelper.returnOpener();
45                page.Response.End();
46            }

47        }

48        public static HttpWebResponse getResponse(HttpWebRequest request)
49ExpandedSubBlockStart.gifContractedSubBlock.gif        {
50            try
51ExpandedSubBlockStart.gifContractedSubBlock.gif            {
52                return (HttpWebResponse)request.GetResponse();
53            }

54            catch (WebException e)
55ExpandedSubBlockStart.gifContractedSubBlock.gif            {
56                HttpContext.Current.Response.Write(e.Message);
57                string result = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
58                HttpContext.Current.Response.Write(result);
59                HttpContext.Current.Response.End();
60            }

61            return null;
62        }

63    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值