加载中

With the above in place we can register it in AuthConfig.cs using the following code.

OAuthWebSecurity.RegisterClient(new TwitterClientEx(
    consumerKey: ConfigurationManager.AppSettings["consumerKey"],
    consumerSecret: ConfigurationManager.AppSettings["consumerSecret"]), "Twitter", null);

//OAuthWebSecurity.RegisterTwitterClient(
//    consumerKey: ConfigurationManager.AppSettings["consumerKey"],
//    consumerSecret: ConfigurationManager.AppSettings["consumerSecret"]);

As we can see above, we have commented out the RegisterTwitterClient static method and instead used the generic RegisterClient method and passed in our own TwitterClientEx instance. The second parameter is simply the Label by which the Client is referred to.

However so far we have merely copied the TwitterClient so we still don’t have our Avatar URL. To load the Avatar and other User Data let’s revisit the VerifyAuthenticationCore method in TwitterClientEx.

The default code has the only the following parameters extracted from the XML Document returned by Twitter.

extraData.AddDataIfNotEmpty(document, "name");
extraData.AddDataIfNotEmpty(document, "location");
extraData.AddDataIfNotEmpty(document, "description");
extraData.AddDataIfNotEmpty(document, "url");

However, instead of the above hardcoding if we have the following Loop then we can extract the complete set of values in the ExtraData dictionary.

XDocument document = LoadXDocumentFromStream(responseStream);
foreach (var node in document.Descendants("user").Nodes<XElement>())
{
if (node.NodeType == XmlNodeType.Element)
{
  extraData.AddDataIfNotEmpty(document, 
((XElement)(node)).Name.LocalName);
}
}

Now that we have retrieved the data required let’s see how we can save it for ourselves.

完成了上面的修改后,我们可以使用下面代码在AuthConfig.cs里注册这个类:
OAuthWebSecurity.RegisterClient(new TwitterClientEx(
    consumerKey: ConfigurationManager.AppSettings["consumerKey"],
    consumerSecret: ConfigurationManager.AppSettings["consumerSecret"]), "Twitter", null);

//OAuthWebSecurity.RegisterTwitterClient(
//    consumerKey: ConfigurationManager.AppSettings["consumerKey"],
//    consumerSecret: ConfigurationManager.AppSettings["consumerSecret"]); 

正如上面我们所看到的,我们注释了RegisterTwitter静态方法,反而使用了常用的RegisterClient方法,然后进入我们自己的TwitterClientEx实例里。第二个参数仅仅是指向客户端的标签。

不过迄今为止我们只是复制了TwitterClient,因此我们仍然没有我们的Avatar URL。为了装载Avatar和其他用户数据,让我们再看一下TwitterClientEx里的VerifyAuthenticationCore方法。

默认的代码只有下面几个参数可从推特返回的XML文档中提取到值。
extraData.AddDataIfNotEmpty(document, "name");
extraData.AddDataIfNotEmpty(document, "location");
extraData.AddDataIfNotEmpty(document, "description");
extraData.AddDataIfNotEmpty(document, "url");
不过可以不用以上的硬编码,如果我们使用下面的循环的话,那么我们可以提取附加数据字典里的所有的值。
XDocument document = LoadXDocumentFromStream(responseStream);
foreach (var node in document.Descendants("user").Nodes<XElement>())
{
if (node.NodeType == XmlNodeType.Element)
{
  extraData.AddDataIfNotEmpty(document,
((XElement)(node)).Name.LocalName);
}
}
现在我们已经获取到所需要的数据了,下一步让我们看看我们是如何保存这些数据的。

Saving ‘ExtraData’

By default the ViewModel objects and Data Model objects are bunched together in Model\UserAccounts.cs file that has multiple class files. Even though I dislike multiple classes per file, I’ll ignore it for the moment and we’ll simply extract the UserProfile class to a new Model\Account folder.

In this folder we will add our ExtraData class. The POCO looks as follows

public class ExtraData
{
public int Id { get; set; }
public string AccessToken { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public UserProfile ParentUserProfile { get; set; }
public int UserProfileUserId { get; set; }
}

For brevity we will refrain from saving all the 35 possible values that can be returned in ExtraData resulting from the Authentication.

The POCO has a parent-child relationship established with the UserProfile object.

In the AccountController, the ExternalLoginCallback method is called after user returns from Twitter’s Authentication page. Here the result variable retrieves all the information returned after a successful Authentication. We populate our ExtraData POCO from the result here.

保存“附加数据”

默认情况下ViewModel对象和数据模型对象是一起挤在有多个类的Model\UserAccounts.cs文件里的。即使我不喜欢每个文件里有多个类,这个时刻我将忽略这种情形,我们只提取UserPfofile类到新的文件夹Model\Account下。

我们将在这个文件夹里增加ExtraData类。POCO看起来如下:
public class ExtraData
{
public int Id { get; set; }
public string AccessToken { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public UserProfile ParentUserProfile { get; set; }
public int UserProfileUserId { get; set; }
}

为了简单起见,我们将不是存储所有从认证返回的附加数据里的35个值。

POCO与UserProfile对象建立了父子关系。

在AccountController里,用户从推特认证页面返回后就调用ExternalLoginCallback方法。这时结果变量获取到成功认证后返回的所有信息 。我们用这儿得到的结果填写附加数据的POCO对象。

As a next step the boilerplate checks if the user exists locally and for first time access the code redirects user to a confirmation page and requests for UserId to be used in this application. This is where we can update the ExtraData poco into the database. However we need to pass all the data via the RegisterExternalLoginModel to the ExternalLoginConfirmation page. To do this we update the RegisterExternalLoginModel to carry ExtraData with it.

public class RegisterExternalLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
public string ExternalLoginData { get; set; }
public ExtraData AuthenticationProviderData { get; set; }
}

In the View we add a set of Labels and Hidden Variables and an Image to represent the ExtraData on the View. There we have it, Authentication with Avataar.

auth-with-avatar

Once we click Register, the ExtraData is saved in the Application’s database and we can retrieve and use it anytime we want.

下一步,样板文件检查是否有这样的本地用户存在,对于第一次访问的用户来说,代码会重定向用户到确认页面,要求输入应用的UserId。在这儿我们能更新附加数据的POCO到数据库了。不过,我们需要通过RegisterExternalLoginModel传递所有的数据到ExternalLoginConfirmation页面。为了完成这个任务,我们修改RegisterExternalLoginModel,用它来传递附加数据。
public class RegisterExternalLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
public string ExternalLoginData { get; set; }
public ExtraData AuthenticationProviderData { get; set; }
}

为了在页面上显示附加数据,我们在页面里增加了一组标签和隐藏变量,以及一张图像。这时我们拥有了Avatar的认证结果。

auth-with-avatar

一旦我们点击了注册,附加数据就存储到应用的数据库了,那么我们就可以在我们需要的任何时候获取和使用了。

Example Usage

Now that we have seen how to Authenticate against Twitter or other OAuth providers we can use this technique for creating a Disqus like commenting system or a StackOverflow style Forum or any ‘Socially connected’ site we want.

The default implementation that comes out of the box with ASP.NET is a little light for direct practical usage but as we saw it’s not really difficult to extend it to our benefit.

Conclusion

We saw how we can build our ASP.NET application to use Twitter for Authentication. The usage scenario discussed was only the tip of the iceberg. DotNetOpenAuth is a powerful library and hidden under the lightweight wrappers created by the ASP.NET team is a real powerhouse framework that can take care of a lot of your Social Media integration requirements.

Download the entire source code of this article (Github)

示例的用途

      既然我们已经明白如何对推特和其他OAuth服务提供商用户进行认证,那么我们可以使用这个技术创建像评论系统、StackOverflow风格的论坛那样的讨论版或者任何我们所想到的“互联的社交”站点。
       来自于ASP.NET的默认实现要直接在实际中使用确实有点单薄,然而正如我们所看到的:扩展默认实现来满足我们的应用真的不难。

结论

      我们看到了我们是如何构建使用推特认证的ASP.NET应用的。所讨论的应用场景仅仅是是冰山的一角。DotNetOpenAuth是一个强大的库,而真正强大的框架是隐藏在ASP.NET团队创建的这个轻量级包的下方,它关注于大量社交媒体的综合需求。

下载这篇文章的全部源代码(GitHub)

返回顶部
顶部