ASP.NET MVC 4 使用 OAuth
这个教程向你展示了如何创建一个ASP.NET MVC 4的web应用,能让用户用外部提供方的证书(比如Facebook, Twitter, Microsoft,或Google)登陆,然后将源自那些提供方的一些功能集成进你的web应用。为简单起见,本教程主要讲述与Facebook的证书一起工作。
在你的web应用中启用这些证书提供了一个重要的优势,因为数百万用户已经有这些外部提供方的帐号。如果不是必须创建并且记住一组新的证书,这些用户可能更倾向于注册你的网站。而且当一个用户通过某一个提供方登陆以后,你可以引入提供方的社会化动作。
你将需要构建的
本指南主要有两个目标:
- 使用户可以通过开放授权服务者提供的凭据登录
- 从第三方获取账号信息并通过在你的站点上完善账户信息
虽然本文的例子只演示了将facebook作为授权服务提供者,但是你可以修改代码去使用任意一个第三方的服务提供者.那些实现的步骤会合你在本文中看到的非常类似.你只有在直接调用第三方提供的API集合时才会发现一些显著的差异.
先决条件
而且,本文假设你具有ASP.NET MVC与Visual Studio的基础知识。如果你需要一个ASP.NET MVC 4的介绍, 请看 ASP.NET MVC 4介绍.
创建工程
在Visual Studio里创建一个新的 ASP.NET MVC 4 Web Application,命名它为 "OAuthMVC"。你可以选择目标为.NET Framework 4.5 或 4中任意一个。
在 New ASP.NET MVC 4 Project 窗口, 选择 Internet Application 并保留 Razor 作为视图引擎。
启用一个提供者
当你用Internet Application模板创建出一个MVC 4 web application时,这个工程在App_Start目录创建了一个名为AuthConfig.cs的文件。
AuthConfig文件包含了针对外部证书提供方的客户注册代码。默认情况下,这些代码被注释掉了,所以没有外部提供者被启用。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
// To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, and Twitter,
|
06 |
// you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=252166
|
08 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
12 |
//OAuthWebSecurity.RegisterTwitterClient(
|
14 |
// consumerSecret: "");
|
16 |
//OAuthWebSecurity.RegisterFacebookClient(
|
20 |
//OAuthWebSecurity.RegisterGoogleClient();
|
你必须反注册这些代码,以便使用外部的客户证书。你只需反注册你想纳入你的网站的提供方。对本教程,你只要启用Facebook证书。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
09 |
//OAuthWebSecurity.RegisterTwitterClient(
|
11 |
// consumerSecret: "");
|
13 |
OAuthWebSecurity.RegisterFacebookClient(
|
17 |
//OAuthWebSecurity.RegisterGoogleClient();
|
注意上面的例子,方法包含了注册参数的空字符串。如果你想现在运行这个应用,应用会抛出一个参数异常,因为这个参数不允许空字符串。为了给出合法的值,你必须像下一节显示的那样,在外部提供方注册你的网站。
在外部提供方注册
要通过来自外部提供方的证书鉴定用户,你必须在提供方注册你的网站。当你注册你的网站时,你将会收到一些参数(比如key或id,以及密码),以便注册客户时包含进去。你必须在你想使用的提供方有一个帐号。
本教程没有呈现出在这些提供方进行注册的所有必须的操作步骤。这些步骤通常是不难的。为了成功的注册你的网站,按照那些网站提供的指示去做。要开始注册你的网站,看看这些开发者网站:
在Facebook注册你的网站时,你可以规定"localhost"为网站域名,"http://localhost/"为网址,像下面图片显示的那样。使用localhost对大多数提供方有效,但目前对Microsoft提供方无效。对Microsoft提供方,你必须包含一个合法的web网站地址。
在前面的图片中,app id,app secret 和contact email的值被剔除了。当你真正注册你的网站时,那些值将会显现。你要注意app id 和app secret的值,因为你将会把它们加到你的应用,
创建测试用户
如果你不介意使用一个已存在的Facebook帐号来测试你的网站,你可以跳过本节。
你能很容易的在Facebook app管理页面中,为你的应用创建测试用户。你能用这些测试帐号登录你的网站。创建测试用户要点击左边导航格子的Roles链接,并点击Create链接。
Facebook网站自动创建你申请的数目的测试帐号。
给应用添加来自提供方的id与secret
现在你收到了来自Facebook的id和secret,回到AuthConfig文件把它们作为参数值增加进去。下面显示的数值不是真实的数值。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
09 |
//OAuthWebSecurity.RegisterTwitterClient(
|
11 |
// consumerSecret: "");
|
13 |
OAuthWebSecurity.RegisterFacebookClient(
|
14 |
appId: "111111111111111" ,
|
15 |
appSecret: "a1a1aa111111111a111a111aaa111111" );
|
17 |
//OAuthWebSecurity.RegisterGoogleClient();
|
用外部证书登录
那就是在你的网站启用外部证书全部要做的。运行你的应用点击右上角的login链接。模版自动识别出你注册了Facebook作为提供方,并为这个提供方包含了一个按钮。如果你注册了多个提供方,一个按钮对应一个会自动包括进来。
本教程没有覆盖怎样为外部提供方客制化登录按钮。需要那些信息,可以看使用OAuth/OpenID时客制化登录界面。
点击Facebook按钮以Facebook证书登录。当你选择了外部提供方的一个,你将被重定向到那个网站,并在其服务提示下登录。
下图显示了Facebook的登录界面。它标明你在用名为oauthmvcexample的Facebook帐号登录一个网站。
用Facebook证书登录以后,一个页面告诉用户这个网站将访问其基本的信息。
选择 Go to App以后, 用户必须在该网站注册。下图显示了一个用户用Facebook证书登录以后的注册页面。用户名被典型的用一个来自提供方的名字预填充。
点击 Register 完成注册。关闭浏览器。
你可以看到新的帐号已经被加到你的数据库。在Server Explorer里,打开DefaultConnection数据库并打开Tables目录。
右击 UserProfile 表选择 Show Table Data。
你将看到你增加的新帐号。看看webpage_OAuthMembership表中的数据。你会看到为你刚增加的帐号,有关外部提供方的的更多数据。
如果你只是想启用外部鉴权,你已经完成了。然而你可以进一步将来自提供方的信息集成进新用户注册过程,就像下面几节显示的那样。
为附加的用户信息创建模型
正如你在前面几节注意到的,你不需要获得任何附加的信息来使内建的注册去工作。但是,大多数提供方返回了关于用户的附加信息。下面几节显示了怎样保留该信息并将它存入数据库。特别的,你将保留这些值,用户的全名,用户个人主页的URI,以及表明Facebook是否验证了该帐号的一个值。
你将使用代码首先迁移来增加一个表,以便存储附加用户信息。你在增加表到已存在的数据库,因此首先你需要创建一个当前数据库的快照。通过创建当前数据库的快照,你可以以后创建一个仅包含新增表的迁移。要创建当前数据库快照:
- 打开 Package Manager Console
- 运行命令 enable-migrations
- 运行命令 add-migration initial –IgnoreChanges
- 运行命令 update-database
现在你要增加新的属性。在Models目录,打开AccountModels.cs文件,找到RegisterExternalLoginModel类。RegisterExternalLoginModel类持有由鉴权提供方返回的数值。增加名为FullName 与 Link的属性,像下面突出的那样。
01 |
public class RegisterExternalLoginModel
|
04 |
[Display(Name = "User name" )]
|
05 |
public string UserName { get ; set ; }
|
07 |
public string ExternalLoginData { get ; set ; }
|
09 |
[Display(Name = "Full name" )]
|
10 |
public string FullName { get ; set ; }
|
12 |
[Display(Name = "Personal page link" )]
|
13 |
public string Link { get ; set ; }
|
同样在AccountModels.cs, 增加一个名为ExtraUserInformation的新类。这个类代表了将在数据库创建的新表。
1 |
[Table( "ExtraUserInformation" )]
|
2 |
public class ExternalUserInformation
|
4 |
public int Id { get ; set ; }
|
5 |
public int UserId { get ; set ; }
|
6 |
public string FullName { get ; set ; }
|
7 |
public string Link { get ; set ; }
|
8 |
public bool ? Verified { get ; set ; }
|
在UsersContext类里,增加下面突出的代码,为新类创建一个DbSet属性。
01 |
public class UsersContext : DbContext
|
04 |
: base ( "DefaultConnection" )
|
08 |
public DbSet<UserProfile> UserProfiles { get ; set ; }
|
09 |
public DbSet<ExternalUserInformation> ExternalUsers { get ; set ; }
|
现在你准备好创建新表了。再次打开 Package Manager Console,这次:
- 运行命令 add-migration AddExtraUserInformation
- 运行命令 update-database
新表现在在数据库出现了。
取得附加的数据
有两个方法获得附加的用户数据。第一个是保留返回的用户数据,默认是在鉴权请求的过程中。第二个方法是特定的调用提供方的 API并请求更多的信息。FullName 与 Link的值自动被Facebook返回。Facebook是否已验证帐号的一个表示数值,是通过一次对Facebook API的调用获得的。首先你要为FullName 和 Link填充值,在此之后,你会得到验证的值。
为了获得额外的用户数据, 打开在Controllers 目录的 AccountController.cs 文件。
这个文件包含了登录、注册以及管理帐号的逻辑。特别的,注意名为ExternalLoginCallback和ExternalLoginConfirmation的方法。在这些方法内,你为你的应用可增加客制化的外部登录操作代码。ExternalLoginCallback方法第一行包含:
1 |
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication( |
2 |
Url.Action( "ExternalLoginCallback" , new { ReturnUrl = returnUrl }));
|
额外的用户数据在AuthenticationResult对象的ExtraData属性中返回,该对象由VerifyAuthentication方法返回。Facebook在ExtraData属性中包含了下面一些值:
- id
- name
- link
- gender
- accesstoken
其他提供方在ExtraData属性中有类似但稍许不同的数据。
如果用户是你的网站的新用户,你会获得一些额外的数据并将其传给确认视图。该方法的最后一块代码只在用户是你网站的新用户 时运行。替代下面这行:
1 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
3 |
UserName = result.UserName,
|
4 |
ExternalLoginData = loginData
|
替换为这行:
1 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
3 |
UserName = result.UserName,
|
4 |
ExternalLoginData = loginData,
|
5 |
FullName = result.ExtraData[ "name" ],
|
6 |
Link = result.ExtraData[ "link" ]
|
这个修改只是包括了FullName 与 Link属性的值。
在ExternalLoginConfirmation 方法里,像下面突出显示的那样修改代码,以便保存附加的用户信息。
03 |
// Insert name into the profile table
|
04 |
UserProfile newUser = db.UserProfiles.Add( new UserProfile { UserName = model.UserName });
|
07 |
db.ExternalUsers.Add( new ExternalUserInformation
|
09 |
UserId = newUser.UserId,
|
10 |
FullName = model.FullName,
|
15 |
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
|
16 |
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false );
|
18 |
return RedirectToLocal(returnUrl);
|
22 |
ModelState.AddModelError( "UserName" , "User name already exists. Please enter a different user name." );
|
调整视图
你从提供方获得的附加的用户数据将被显示于注册页面。
在 Views/ Account 目录,打开 ExternalLoginConfirmation.cshtml。在已存在的user name字段下面,增加FullName, Link, 和 PictureLink字段。
2 |
@Html.LabelFor(m => m.FullName)
|
3 |
@Html.TextBoxFor(m => m.FullName)
|
6 |
@Html.LabelFor(m => m.Link)
|
7 |
@Html.TextBoxFor(m => m.Link)
|
现在你几乎已经准备好运行应用,并且用保存的附加信息注册一个新用户。你必须有一个尚未在该网站注册的帐号。你可以使用一个不同的测试帐号,也可以删除UserProfile和webpages_OAuthMembership 表中的你想重新使用的帐号对应行。通过删除那些行,你能确保该帐号能再次注册。
运行应用并注册新用户。注意这次确认页面包含了更多的数值。
完成注册以后,关闭浏览器。看看数据库,留心ExtraUserInformation表中的新的值。
为Facebook API安装NuGet包
Facebook 提供了一个 API 给你调用来执行操作。你可以或者通过直接发送HTTP请求,或者通过安装一个帮助发送那些请求的NuGet包,来调用Facebook API。使用一个NuGet包已被本教程显示,但安装NuGet包不是基本的。这个教程显示了如何使用Facebook C# SDK包。还有其他的辅助Facebook API调用的NuGet包。
从 Manage NuGet Packages 窗口,选择 Facebook C# SDK package。
你将使用 Facebook C# SDK 来调用一个操作,该操作请求用户的 access token (访问令牌)。下一节显示了如何得到access token。
取得 access token
大多数外部的提供方在用户鉴权被验证以后返回一个access token。这个access token非常重要,因为它使你可以调用只能被鉴权用户使用的操作。因此,当你想提供更多功能性时,获得并保存access token是基本的。
取决于外部的提供方,access token可能只在一个有限数值的时间内有效。为了确保你具有一个有效的access token,你要在每次用户登录的时候获得它,并将它保存为session值而不是保存进数据库。
在 ExternalLoginCallback 方法里,access token也被送回到AuthenticationResult对象的ExtraData属性。添加如下突出的代码到 ExternalLoginCallback 以便将 access token 保存进 Session 对象。这些代码在每次用户用Facebook帐号登录时会运行。
02 |
public ActionResult ExternalLoginCallback( string returnUrl)
|
04 |
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
|
05 |
Url.Action( "ExternalLoginCallback" , new { ReturnUrl = returnUrl }));
|
06 |
if (!result.IsSuccessful)
|
08 |
return RedirectToAction( "ExternalLoginFailure" );
|
11 |
if (result.ExtraData.Keys.Contains( "accesstoken" ))
|
13 |
Session[ "facebooktoken" ] = result.ExtraData[ "accesstoken" ];
|
16 |
if (OAuthWebSecurity.Login(
|
18 |
result.ProviderUserId,
|
19 |
createPersistentCookie: false ))
|
21 |
return RedirectToLocal(returnUrl);
|
24 |
if (User.Identity.IsAuthenticated)
|
26 |
// If the current user is logged in add the new account
|
27 |
OAuthWebSecurity.CreateOrUpdateAccount(
|
29 |
result.ProviderUserId,
|
31 |
return RedirectToLocal(returnUrl);
|
35 |
// User is new, ask for their desired membership name
|
36 |
string loginData = OAuthWebSecurity.SerializeProviderUserId(
|
38 |
result.ProviderUserId);
|
39 |
ViewBag.ProviderDisplayName =
|
40 |
OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
|
41 |
ViewBag.ReturnUrl = returnUrl;
|
42 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
44 |
UserName = result.UserName,
|
45 |
ExternalLoginData = loginData,
|
46 |
FullName = result.ExtraData[ "name" ],
|
47 |
Link = result.ExtraData[ "link" ]
|
尽管这个例子从Facebook获得了一个access token,你可以通过同样的名为“accesstoken”的关键字从任何外部提供方获得access token。
为了防止令牌在用户已退出登录以后仍然保持,你可以添加如下突出的代码到AccountController中的 LogOff方法。
2 |
[ValidateAntiForgeryToken] |
3 |
public ActionResult LogOff()
|
6 |
Session.Remove( "facebooktoken" );
|
8 |
return RedirectToAction( "Index" , "Home" );
|
获得需要访问令牌的用户信息
现在你已经保存了access token并且安装了Facebook C# SDK包,你可以一起使用它们去从Facebook请求附加的用户信息。在ExternalLoginConfirmation方法中,通过传递access token的值创建了一个FacebookClient类的实例。请求当前鉴权用户的verified属性值。verified属性表明了Facebook是否已经通过一些其他的方法,比如给蜂窝电话发送一个信息,验证了该帐号。将这个数值保存进数据库。
03 |
// Insert name into the profile table
|
04 |
UserProfile newUser = db.UserProfiles.Add( new UserProfile { UserName = model.UserName });
|
07 |
bool facebookVerified;
|
09 |
var client = new Facebook.FacebookClient(Session[ "facebooktoken" ].ToString());
|
10 |
dynamic response = client.Get( "me" , new { fields = "verified" });
|
11 |
if (response.ContainsKey( "verified" ))
|
13 |
facebookVerified = response[ "verified" ];
|
17 |
facebookVerified = false ;
|
20 |
db.ExternalUsers.Add( new ExternalUserInformation
|
22 |
UserId = newUser.UserId,
|
23 |
FullName = model.FullName,
|
25 |
Verified = facebookVerified
|
29 |
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
|
30 |
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false );
|
32 |
return RedirectToLocal(returnUrl);
|
你将需要再一次或者删除数据库中用户的记录,或者使用一个不同的Facebook帐号。
运行应用,并且注册新用户。看看ExtraUserInformation表 Verified属性的值。
总结
本教程中,你创建了集成Facebook来进行用户鉴权并注册数据的网站。你学习了MVC4 web应用创立的默认的行为,以及如何客制化那个默认的行为。
ASP.NET MVC 4 使用 OAuth
这个教程向你展示了如何创建一个ASP.NET MVC 4的web应用,能让用户用外部提供方的证书(比如Facebook, Twitter, Microsoft,或Google)登陆,然后将源自那些提供方的一些功能集成进你的web应用。为简单起见,本教程主要讲述与Facebook的证书一起工作。
在你的web应用中启用这些证书提供了一个重要的优势,因为数百万用户已经有这些外部提供方的帐号。如果不是必须创建并且记住一组新的证书,这些用户可能更倾向于注册你的网站。而且当一个用户通过某一个提供方登陆以后,你可以引入提供方的社会化动作。
你将需要构建的
本指南主要有两个目标:
- 使用户可以通过开放授权服务者提供的凭据登录
- 从第三方获取账号信息并通过在你的站点上完善账户信息
虽然本文的例子只演示了将facebook作为授权服务提供者,但是你可以修改代码去使用任意一个第三方的服务提供者.那些实现的步骤会合你在本文中看到的非常类似.你只有在直接调用第三方提供的API集合时才会发现一些显著的差异.
先决条件
而且,本文假设你具有ASP.NET MVC与Visual Studio的基础知识。如果你需要一个ASP.NET MVC 4的介绍, 请看 ASP.NET MVC 4介绍.
创建工程
在Visual Studio里创建一个新的 ASP.NET MVC 4 Web Application,命名它为 "OAuthMVC"。你可以选择目标为.NET Framework 4.5 或 4中任意一个。
在 New ASP.NET MVC 4 Project 窗口, 选择 Internet Application 并保留 Razor 作为视图引擎。
启用一个提供者
当你用Internet Application模板创建出一个MVC 4 web application时,这个工程在App_Start目录创建了一个名为AuthConfig.cs的文件。
AuthConfig文件包含了针对外部证书提供方的客户注册代码。默认情况下,这些代码被注释掉了,所以没有外部提供者被启用。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
// To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, and Twitter,
|
06 |
// you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=252166
|
08 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
12 |
//OAuthWebSecurity.RegisterTwitterClient(
|
14 |
// consumerSecret: "");
|
16 |
//OAuthWebSecurity.RegisterFacebookClient(
|
20 |
//OAuthWebSecurity.RegisterGoogleClient();
|
你必须反注册这些代码,以便使用外部的客户证书。你只需反注册你想纳入你的网站的提供方。对本教程,你只要启用Facebook证书。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
09 |
//OAuthWebSecurity.RegisterTwitterClient(
|
11 |
// consumerSecret: "");
|
13 |
OAuthWebSecurity.RegisterFacebookClient(
|
17 |
//OAuthWebSecurity.RegisterGoogleClient();
|
注意上面的例子,方法包含了注册参数的空字符串。如果你想现在运行这个应用,应用会抛出一个参数异常,因为这个参数不允许空字符串。为了给出合法的值,你必须像下一节显示的那样,在外部提供方注册你的网站。
在外部提供方注册
要通过来自外部提供方的证书鉴定用户,你必须在提供方注册你的网站。当你注册你的网站时,你将会收到一些参数(比如key或id,以及密码),以便注册客户时包含进去。你必须在你想使用的提供方有一个帐号。
本教程没有呈现出在这些提供方进行注册的所有必须的操作步骤。这些步骤通常是不难的。为了成功的注册你的网站,按照那些网站提供的指示去做。要开始注册你的网站,看看这些开发者网站:
在Facebook注册你的网站时,你可以规定"localhost"为网站域名,"http://localhost/"为网址,像下面图片显示的那样。使用localhost对大多数提供方有效,但目前对Microsoft提供方无效。对Microsoft提供方,你必须包含一个合法的web网站地址。
在前面的图片中,app id,app secret 和contact email的值被剔除了。当你真正注册你的网站时,那些值将会显现。你要注意app id 和app secret的值,因为你将会把它们加到你的应用,
创建测试用户
如果你不介意使用一个已存在的Facebook帐号来测试你的网站,你可以跳过本节。
你能很容易的在Facebook app管理页面中,为你的应用创建测试用户。你能用这些测试帐号登录你的网站。创建测试用户要点击左边导航格子的Roles链接,并点击Create链接。
Facebook网站自动创建你申请的数目的测试帐号。
给应用添加来自提供方的id与secret
现在你收到了来自Facebook的id和secret,回到AuthConfig文件把它们作为参数值增加进去。下面显示的数值不是真实的数值。
01 |
public static class AuthConfig
|
03 |
public static void RegisterAuth()
|
05 |
//OAuthWebSecurity.RegisterMicrosoftClient(
|
09 |
//OAuthWebSecurity.RegisterTwitterClient(
|
11 |
// consumerSecret: "");
|
13 |
OAuthWebSecurity.RegisterFacebookClient(
|
14 |
appId: "111111111111111" ,
|
15 |
appSecret: "a1a1aa111111111a111a111aaa111111" );
|
17 |
//OAuthWebSecurity.RegisterGoogleClient();
|
用外部证书登录
那就是在你的网站启用外部证书全部要做的。运行你的应用点击右上角的login链接。模版自动识别出你注册了Facebook作为提供方,并为这个提供方包含了一个按钮。如果你注册了多个提供方,一个按钮对应一个会自动包括进来。
本教程没有覆盖怎样为外部提供方客制化登录按钮。需要那些信息,可以看使用OAuth/OpenID时客制化登录界面。
点击Facebook按钮以Facebook证书登录。当你选择了外部提供方的一个,你将被重定向到那个网站,并在其服务提示下登录。
下图显示了Facebook的登录界面。它标明你在用名为oauthmvcexample的Facebook帐号登录一个网站。
用Facebook证书登录以后,一个页面告诉用户这个网站将访问其基本的信息。
选择 Go to App以后, 用户必须在该网站注册。下图显示了一个用户用Facebook证书登录以后的注册页面。用户名被典型的用一个来自提供方的名字预填充。
点击 Register 完成注册。关闭浏览器。
你可以看到新的帐号已经被加到你的数据库。在Server Explorer里,打开DefaultConnection数据库并打开Tables目录。
右击 UserProfile 表选择 Show Table Data。
你将看到你增加的新帐号。看看webpage_OAuthMembership表中的数据。你会看到为你刚增加的帐号,有关外部提供方的的更多数据。
如果你只是想启用外部鉴权,你已经完成了。然而你可以进一步将来自提供方的信息集成进新用户注册过程,就像下面几节显示的那样。
为附加的用户信息创建模型
正如你在前面几节注意到的,你不需要获得任何附加的信息来使内建的注册去工作。但是,大多数提供方返回了关于用户的附加信息。下面几节显示了怎样保留该信息并将它存入数据库。特别的,你将保留这些值,用户的全名,用户个人主页的URI,以及表明Facebook是否验证了该帐号的一个值。
你将使用代码首先迁移来增加一个表,以便存储附加用户信息。你在增加表到已存在的数据库,因此首先你需要创建一个当前数据库的快照。通过创建当前数据库的快照,你可以以后创建一个仅包含新增表的迁移。要创建当前数据库快照:
- 打开 Package Manager Console
- 运行命令 enable-migrations
- 运行命令 add-migration initial –IgnoreChanges
- 运行命令 update-database
现在你要增加新的属性。在Models目录,打开AccountModels.cs文件,找到RegisterExternalLoginModel类。RegisterExternalLoginModel类持有由鉴权提供方返回的数值。增加名为FullName 与 Link的属性,像下面突出的那样。
01 |
public class RegisterExternalLoginModel
|
04 |
[Display(Name = "User name" )]
|
05 |
public string UserName { get ; set ; }
|
07 |
public string ExternalLoginData { get ; set ; }
|
09 |
[Display(Name = "Full name" )]
|
10 |
public string FullName { get ; set ; }
|
12 |
[Display(Name = "Personal page link" )]
|
13 |
public string Link { get ; set ; }
|
同样在AccountModels.cs, 增加一个名为ExtraUserInformation的新类。这个类代表了将在数据库创建的新表。
1 |
[Table( "ExtraUserInformation" )]
|
2 |
public class ExternalUserInformation
|
4 |
public int Id { get ; set ; }
|
5 |
public int UserId { get ; set ; }
|
6 |
public string FullName { get ; set ; }
|
7 |
public string Link { get ; set ; }
|
8 |
public bool ? Verified { get ; set ; }
|
在UsersContext类里,增加下面突出的代码,为新类创建一个DbSet属性。
01 |
public class UsersContext : DbContext
|
04 |
: base ( "DefaultConnection" )
|
08 |
public DbSet<UserProfile> UserProfiles { get ; set ; }
|
09 |
public DbSet<ExternalUserInformation> ExternalUsers { get ; set ; }
|
现在你准备好创建新表了。再次打开 Package Manager Console,这次:
- 运行命令 add-migration AddExtraUserInformation
- 运行命令 update-database
新表现在在数据库出现了。
取得附加的数据
有两个方法获得附加的用户数据。第一个是保留返回的用户数据,默认是在鉴权请求的过程中。第二个方法是特定的调用提供方的 API并请求更多的信息。FullName 与 Link的值自动被Facebook返回。Facebook是否已验证帐号的一个表示数值,是通过一次对Facebook API的调用获得的。首先你要为FullName 和 Link填充值,在此之后,你会得到验证的值。
为了获得额外的用户数据, 打开在Controllers 目录的 AccountController.cs 文件。
这个文件包含了登录、注册以及管理帐号的逻辑。特别的,注意名为ExternalLoginCallback和ExternalLoginConfirmation的方法。在这些方法内,你为你的应用可增加客制化的外部登录操作代码。ExternalLoginCallback方法第一行包含:
1 |
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication( |
2 |
Url.Action( "ExternalLoginCallback" , new { ReturnUrl = returnUrl }));
|
额外的用户数据在AuthenticationResult对象的ExtraData属性中返回,该对象由VerifyAuthentication方法返回。Facebook在ExtraData属性中包含了下面一些值:
- id
- name
- link
- gender
- accesstoken
其他提供方在ExtraData属性中有类似但稍许不同的数据。
如果用户是你的网站的新用户,你会获得一些额外的数据并将其传给确认视图。该方法的最后一块代码只在用户是你网站的新用户 时运行。替代下面这行:
1 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
3 |
UserName = result.UserName,
|
4 |
ExternalLoginData = loginData
|
替换为这行:
1 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
3 |
UserName = result.UserName,
|
4 |
ExternalLoginData = loginData,
|
5 |
FullName = result.ExtraData[ "name" ],
|
6 |
Link = result.ExtraData[ "link" ]
|
这个修改只是包括了FullName 与 Link属性的值。
在ExternalLoginConfirmation 方法里,像下面突出显示的那样修改代码,以便保存附加的用户信息。
03 |
// Insert name into the profile table
|
04 |
UserProfile newUser = db.UserProfiles.Add( new UserProfile { UserName = model.UserName });
|
07 |
db.ExternalUsers.Add( new ExternalUserInformation
|
09 |
UserId = newUser.UserId,
|
10 |
FullName = model.FullName,
|
15 |
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
|
16 |
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false );
|
18 |
return RedirectToLocal(returnUrl);
|
22 |
ModelState.AddModelError( "UserName" , "User name already exists. Please enter a different user name." );
|
调整视图
你从提供方获得的附加的用户数据将被显示于注册页面。
在 Views/ Account 目录,打开 ExternalLoginConfirmation.cshtml。在已存在的user name字段下面,增加FullName, Link, 和 PictureLink字段。
2 |
@Html.LabelFor(m => m.FullName)
|
3 |
@Html.TextBoxFor(m => m.FullName)
|
6 |
@Html.LabelFor(m => m.Link)
|
7 |
@Html.TextBoxFor(m => m.Link)
|
现在你几乎已经准备好运行应用,并且用保存的附加信息注册一个新用户。你必须有一个尚未在该网站注册的帐号。你可以使用一个不同的测试帐号,也可以删除UserProfile和webpages_OAuthMembership 表中的你想重新使用的帐号对应行。通过删除那些行,你能确保该帐号能再次注册。
运行应用并注册新用户。注意这次确认页面包含了更多的数值。
完成注册以后,关闭浏览器。看看数据库,留心ExtraUserInformation表中的新的值。
为Facebook API安装NuGet包
Facebook 提供了一个 API 给你调用来执行操作。你可以或者通过直接发送HTTP请求,或者通过安装一个帮助发送那些请求的NuGet包,来调用Facebook API。使用一个NuGet包已被本教程显示,但安装NuGet包不是基本的。这个教程显示了如何使用Facebook C# SDK包。还有其他的辅助Facebook API调用的NuGet包。
从 Manage NuGet Packages 窗口,选择 Facebook C# SDK package。
你将使用 Facebook C# SDK 来调用一个操作,该操作请求用户的 access token (访问令牌)。下一节显示了如何得到access token。
取得 access token
大多数外部的提供方在用户鉴权被验证以后返回一个access token。这个access token非常重要,因为它使你可以调用只能被鉴权用户使用的操作。因此,当你想提供更多功能性时,获得并保存access token是基本的。
取决于外部的提供方,access token可能只在一个有限数值的时间内有效。为了确保你具有一个有效的access token,你要在每次用户登录的时候获得它,并将它保存为session值而不是保存进数据库。
在 ExternalLoginCallback 方法里,access token也被送回到AuthenticationResult对象的ExtraData属性。添加如下突出的代码到 ExternalLoginCallback 以便将 access token 保存进 Session 对象。这些代码在每次用户用Facebook帐号登录时会运行。
02 |
public ActionResult ExternalLoginCallback( string returnUrl)
|
04 |
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
|
05 |
Url.Action( "ExternalLoginCallback" , new { ReturnUrl = returnUrl }));
|
06 |
if (!result.IsSuccessful)
|
08 |
return RedirectToAction( "ExternalLoginFailure" );
|
11 |
if (result.ExtraData.Keys.Contains( "accesstoken" ))
|
13 |
Session[ "facebooktoken" ] = result.ExtraData[ "accesstoken" ];
|
16 |
if (OAuthWebSecurity.Login(
|
18 |
result.ProviderUserId,
|
19 |
createPersistentCookie: false ))
|
21 |
return RedirectToLocal(returnUrl);
|
24 |
if (User.Identity.IsAuthenticated)
|
26 |
// If the current user is logged in add the new account
|
27 |
OAuthWebSecurity.CreateOrUpdateAccount(
|
29 |
result.ProviderUserId,
|
31 |
return RedirectToLocal(returnUrl);
|
35 |
// User is new, ask for their desired membership name
|
36 |
string loginData = OAuthWebSecurity.SerializeProviderUserId(
|
38 |
result.ProviderUserId);
|
39 |
ViewBag.ProviderDisplayName =
|
40 |
OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
|
41 |
ViewBag.ReturnUrl = returnUrl;
|
42 |
return View( "ExternalLoginConfirmation" , new RegisterExternalLoginModel
|
44 |
UserName = result.UserName,
|
45 |
ExternalLoginData = loginData,
|
46 |
FullName = result.ExtraData[ "name" ],
|
47 |
Link = result.ExtraData[ "link" ]
|
尽管这个例子从Facebook获得了一个access token,你可以通过同样的名为“accesstoken”的关键字从任何外部提供方获得access token。
为了防止令牌在用户已退出登录以后仍然保持,你可以添加如下突出的代码到AccountController中的 LogOff方法。
2 |
[ValidateAntiForgeryToken] |
3 |
public ActionResult LogOff()
|
6 |
Session.Remove( "facebooktoken" );
|
8 |
return RedirectToAction( "Index" , "Home" );
|
获得需要访问令牌的用户信息
现在你已经保存了access token并且安装了Facebook C# SDK包,你可以一起使用它们去从Facebook请求附加的用户信息。在ExternalLoginConfirmation方法中,通过传递access token的值创建了一个FacebookClient类的实例。请求当前鉴权用户的verified属性值。verified属性表明了Facebook是否已经通过一些其他的方法,比如给蜂窝电话发送一个信息,验证了该帐号。将这个数值保存进数据库。
03 |
// Insert name into the profile table
|
04 |
UserProfile newUser = db.UserProfiles.Add( new UserProfile { UserName = model.UserName });
|
07 |
bool facebookVerified;
|
09 |
var client = new Facebook.FacebookClient(Session[ "facebooktoken" ].ToString());
|
10 |
dynamic response = client.Get( "me" , new { fields = "verified" });
|
11 |
if (response.ContainsKey( "verified" ))
|
13 |
facebookVerified = response[ "verified" ];
|
17 |
facebookVerified = false ;
|
20 |
db.ExternalUsers.Add( new ExternalUserInformation
|
22 |
UserId = newUser.UserId,
|
23 |
FullName = model.FullName,
|
25 |
Verified = facebookVerified
|
29 |
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
|
30 |
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false );
|
32 |
return RedirectToLocal(returnUrl);
|
你将需要再一次或者删除数据库中用户的记录,或者使用一个不同的Facebook帐号。
运行应用,并且注册新用户。看看ExtraUserInformation表 Verified属性的值。
总结
本教程中,你创建了集成Facebook来进行用户鉴权并注册数据的网站。你学习了MVC4 web应用创立的默认的行为,以及如何客制化那个默认的行为。