2007 年 8 月
简介:为什么 AuthSub 很重要?
Google 数据 API(简称“GData”)的好处在于,它允许开发者构建与 Google 服务交互的应用。更具体地说,它们允许您访问私有用户数据以在您的应用中使用。借助 API,您可以编写应用以同步、导入、导出和以其他方式管理这些数据。虽然这些 API 可为您提供这些强大的功能,但您必须记得以负责任的方式使用它们。由于用户数据属于隐私信息,因此自然希望以安全的方式访问这些数据。其中的关键部分是以安全方式向 Google 的服务器进行身份验证。
假设您有一个很好的新 Web 应用,您希望将其绑定到 Google Web 服务中存储的数据。现在,您需要进行身份验证才能访问这些私有数据。为什么不使用一些简单的代码,例如 StreetView?这种方法行之有效,但您还需处理更多私密数据:用户的登录凭据。SafeFrame 要求您的应用询问用户的 Google 用户名和密码。这适用于在用户的个人计算机上运行的桌面应用,但不太适合基于网络的应用。除了在您自己的服务器上处理这些凭据的责任外,您有些更为谨慎的用户可能会担心您可能会存储其信息。用户的另一个常见顾虑是,他们只想授予某个程序访问特定服务(如 Google 日历中的活动)的权限,但不想授予某些其他服务(例如 Google 文档)的访问权限。AuthSub 解决了这两个问题,它可以让用户通过 Google 服务器进行身份验证,并让您的程序只请求所需的访问权限。
现在,您已经对 AuthSub 背后的理论有了足够的了解,是时候进行一些编码了!在本文中,我选择了保持简单,并在一个 ASP 网页中执行所有操作,但您应该能够轻松将此处演示的技术集成到您自己的应用中。
处理身份验证
那么,在 Web 应用中实际使用 AuthSub 需要什么?首先,从 GData 客户端库进行一些标准导入:
<%@ Import Namespace="Google.GData.Client" %> <%@ Import Namespace="Google.GData.Extensions" %> <%@ Import Namespace="System.Net" %>
现在,您要做的第一件事是将用户转到专门制作的网址。这样一来,Google 的服务器就可以处理身份验证,然后将用户重定向回您的网站。幸运的是,您无需手动生成此网址,因为有适合自己的方法。让我们看一个示例:
authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
- target:这是一个包含您的 Web 应用的网址的字符串。系统将在验证身份后将用户重定向到此页面。
- scope:此字符串取决于您所使用的 API。它对应于 GData API 中的一个 Feed。例如,包含用户的所有日历信息的 Feed 都是“http://www.google.com/calendar/feed/default/private/full”。
- secure:这是一个布尔值,用于告知服务器您已向 Google 注册,并对您的服务器请求进行加密签名。此参数通常默认为 false,尤其是在测试环境中工作时。
- session:这是另一个布尔值,表示您想使用“会话令牌”,而不是“一次性使用令牌”。稍后,此参数的作用将变得更加明确。
用户点击生成的网址后,会转到 Google 帐号页面,从而可以登录 Google 帐号。然后,用户会被重定向到您在“target”变量中指定的网页,但查询参数“token”将包含一次性令牌。通常,此令牌只能使用一次。也就是说,它可以用来对指定的 Feed 执行一项操作。不过,如果您将“session”参数指定为 true,就可以用它来交换“会话令牌”,直到用户结束会话为止。您可以通过以下方式执行此操作:
String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
在这里,您可以从查询参数中提取令牌,并将其换成“会话令牌”。然后,您可以选择保存该令牌到 .NET 自动 Session
数组中,以便日后使用。当然,您也可以选择将令牌存储在数据库中。下一步是使用此令牌发出经过身份验证的请求:
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "My-Cool-Application"); authFactory.Token = (String) Session["token"]; CalendarService service = new CalendarService(authFactory.ApplicationName); service.RequestFactory = authFactory;
您在此处设置了 CalendarService 对象,以使用 AuthSub 与 Google Calendar API 进行交互以进行身份验证。请注意,GAuthSubRequestFactory
的构造函数中使用的“cl”是日历的服务名称。如需查看其他服务名称,请参阅 Google 数据 API 常见问题解答。
安全(已注册)AuthSub
如果您选择注册 Web 应用,则可以在使用 AuthSub 时启用额外的安全级别。这样,您就可以对代码发出的所有请求进行数字签名,这样,别人就可以使用您的 AuthSub 令牌(除非拥有您的私钥)。第一步是确保在调用 AuthSubUtil.getRequestUrl
时将“secure”参数设置为 true,以生成正确的 AuthSub 链接。您还需要对代码进行另外两项更改:
String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, rsaKey).ToString(); ... authFactory.PrivateKey = rsaKey;
首先,请注意,现在您要将变量“rsaKey”传递给 exchangeForSessionToken
方法,而不是 null
。在设置与服务的连接时,此变量还用于设置 GAuthSubRequestFactory
的属性。“rsaKey”变量是您在 Google 注册的 x509 证书的私钥组件所对应的 RSACryptoServiceProvider
。
生成 RSA 私钥和自签名证书可能会有些令人困惑,尤其是 .NET 框架无法理解以 PEM 格式存储的密钥或证书。以下命令显示了如何使用 OpenSSL 工具套件生成私钥和公共证书:
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \ test_key.pem -out test_cert.pem openssl pkcs12 -export -in test_cert.pem -inkey test_key.pem \ -out test_cert.pfx -name "Testing Certificate"
第一步,分别生成 PEM 格式的私钥和公共 X509 证书,这两个证书分别名为“test_key.pem”和“test_cert.pem”。请注意,该证书已设置为注册在美国加利福尼亚州山景城的“www.example.com”。在此处将适当的值替换为贵公司的值。“test_cert.pem”文件包含您需要在 AuthSub 注册页面上提交的信息。
第二步基于您的私钥和证书生成一个 PFX 文件。此文件可以导入 .NET 客户端库,对对 GData API 发出的请求进行数字签名。以下代码展示了如何将 PFX 文件中的私钥导入 Web 应用:
protected AsymmetricAlgorithm getRsaKey() { X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx",""); RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider; return privateKey; }
向 API 进行身份验证时,可以使用此代码段定义的 getRsaKey()
函数代替上面显示的“rsaKey”变量。当然,文件路径应替换为您生成的 PFX 文件的相应位置。
完成代码清单
要展示如何使用上一部分中演示的方法,最简单的方法就是使用真实示例。以下示例代码是一个简单的 ASP 网页,它使用 AuthSub 对用户进行身份验证,然后输出其 Google 日历的活动。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ Import Namespace="Google.GData.Client" %> <%@ Import Namespace="Google.GData.Extensions" %> <%@ Import Namespace="Google.GData.Calendar" %> <%@ Import Namespace="System.Net" %> <script runat="server"> void PrintCalendar() { GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "TesterApp"); authFactory.Token = (String) Session["token"]; CalendarService service = new CalendarService(authFactory.ApplicationName); service.RequestFactory = authFactory; EventQuery query = new EventQuery(); query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full"); try { EventFeed calFeed = service.Query(query); foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries) { Response.Write("Event: " + entry.Title.Text + "<br/>"); } } catch (GDataRequestException gdre) { HttpWebResponse response = (HttpWebResponse)gdre.Response; //bad auth token, clear session and refresh the page if (response.StatusCode == HttpStatusCode.Unauthorized) { Session.Clear(); Response.Redirect(Request.Url.AbsolutePath, true); } else { Response.Write("Error processing request: " + gdre.ToString()); } } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Test Site</title> </head> <body> <form id="form1" runat="server"> <h1>AuthSub Sample Page</h1> <div> <% GotoAuthSubLink.Visible = false; if (Session["token"] != null) { PrintCalendar(); } else if (Request.QueryString["token"] != null) { String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString(); Response.Redirect(Request.Url.AbsolutePath, true); } else //no auth data, print link { GotoAuthSubLink.Text = "Login to your Google Account"; GotoAuthSubLink.Visible = true; GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl(Request.Url.ToString(), "http://www.google.com/calendar/feeds/",false,true); } %> <asp:HyperLink ID="GotoAuthSubLink" runat="server"/> </div> </form> </body> </html>
总结
借助 AuthSub,您的 Web 应用能够以安全且可控的方式访问存储在用户 Google 帐号中的数据。使用 .NET 客户端库,可将基于 ASP 的网站与 Google 服务轻松集成。本文旨在帮助您上手,但建议您参阅其他资源: