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应用创立的默认的行为,以及如何客制化那个默认的行为。
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- Web用户的身份验证及WebApi权限验证流程的设计和实现 asp.net mvc AllowAnonymous 不起作用, asp.net mvc 匿名访问
原文地址: https://blog.csdn.net/zjlovety/article/details/17095627 前言:Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能,一个 ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC资源过滤和授权
最近比较忙,博客很久没更新了,很多博友问何时更新博文,因此,今天就花了点时间,写了本篇文章,但愿大家喜欢. 本篇文章不适合初学者,需要对ASP.NET MVC具有一定基础. 本篇文章主要从ASP.NE ...
- 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章 ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...
- Web 应用程序中的安全向量 – ASP.NET MVC 4 系列
Web 程序运行在标准的.基于文本的协议(HTTP 和 HTML)之上,所以特别容易受到自动攻击的伤害.本章主要介绍黑客如何滥用应用程序,以及针对这些问题的应对措施. 威胁:跨站脚本 ...
- Spring MVC中的DispatcherServlet作用
一. DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的 ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC 视图
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器
摘要 本文将对“MVC公告发布系统”的发布公告功能添加日志功能和异常处理功能,借此来讨论ASP.NET MVC中拦截器的使用方法. 一个小难题 我们继续完善“MVC公告发布系统”, ...
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第三篇:ASP.NET MVC全局观
摘要 本文对ASP.NET MVC的全局运行机理进行一个简要的介绍,以使得朋友们更好的理解后续文章. 前言 在上一篇文章中,我们实现了第一个ASP.NET MVC页面.对于没有接触 ...
随机推荐
- Tomcat启动时报错:java.net.UnknownHostException
异常信息如下: INFO: Failed to get local InetAddress for VMID. This is unlikely to matter. At all. We'll ad ...
- InnoDB与MyISAM引擎区别
mysql中InnoDB与MyISAM两种数据库引擎的区别: 一.InnoDB引擎: 1.支持事务性, 2.支持外部键, 3.行级锁, 4.不保存表的具体行数,执行select count(*) fr ...
- java操作mongodb——连接数据库
import com.mongodb.MongoClient; MongoClient mongoClient = new MongoClient(); 连接MongoDB实例,默认为localhos ...
- Beyond Compare V3.2.3 Beta 中文版
软件名称: Beyond Compare V3.2.3 Beta 中文版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win7 / Vista / Win2003 / WinXP 软件大小 ...
- bat脚本学习
工作需求,写个bat脚本来启动自己的守护进程:bat方面完全空白啊~稍微学习了下,记录下来,后面复习! 直接上代码: 示例一:for字符串切割,切割文本中的字符串: test.txt 文本内容如下: ...
- c#的as关键字
类型a as 类型b ,把类型a强制变为类型b
- jenkins 杀死衍生进程
解决方法-1: 在execute shell输入框中加入BUILD_ID=DONTKILLME,即可防止jenkins衍生进程 解决方法-2: 修改/etc/sysconfig/jenkins配置,在 ...
- 常用的html标签大全
html标签大全 一.文字 1.标题文字 <h#>..........</h#> #=1~6:h1为最大字,h6为最小字 2.字体变化 <font>........ ...
- OpenGL编译问题随手记
1.error C2381: "exit" : 重定义:__declspec(noreturn) 不同 编译OpenGL Red Book 的例子时出现错误, stdl ...
- 扯蛋css
使网页旋转代码: javascript:window.i=1;setInterval(function(){i++;document.body.style.cssText+="-webkit ...