MVC中AuthConfig的作用 -- ASP.NET MVC 4 使用 OAuth


ASP.NET MVC 4 使用 OAuth

這個教程向你展示了如何創建一個ASP.NET MVC 4的web應用,能讓用戶用外部提供方的證書(比如Facebook, Twitter, Microsoft,或Google)登陸,然后將源自那些提供方的一些功能集成進你的web應用。為簡單起見,本教程主要講述與Facebook的證書一起工作。

在你的web應用中啟用這些證書提供了一個重要的優勢,因為數百萬用戶已經有這些外部提供方的帳號。如果不是必須創建並且記住一組新的證書,這些用戶可能更傾向於注冊你的網站。而且當一個用戶通過某一個提供方登陸以后,你可以引入提供方的社會化動作。

你將需要構建的

本指南主要有兩個目標:

  1. 使用戶可以通過開放授權服務者提供的憑據登錄
  2. 從第三方獲取賬號信息並通過在你的站點上完善賬戶信息

雖然本文的例子只演示了將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中任意一個。

create project

在 New ASP.NET MVC 4 Project 窗口, 選擇 Internet Application 並保留 Razor 作為視圖引擎。

select Internet Application

啟用一個提供者

當你用Internet Application模板創建出一個MVC 4 web application時,這個工程在App_Start目錄創建了一個名為AuthConfig.cs的文件。

AuthConfig file

AuthConfig文件包含了針對外部證書提供方的客戶注冊代碼。默認情況下,這些代碼被注釋掉了,所以沒有外部提供者被啟用。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
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
07  
08         //OAuthWebSecurity.RegisterMicrosoftClient(
09         //    clientId: "",
10         //    clientSecret: "");
11  
12         //OAuthWebSecurity.RegisterTwitterClient(
13         //    consumerKey: "",
14         //    consumerSecret: "");
15  
16         //OAuthWebSecurity.RegisterFacebookClient(
17         //    appId: "",
18         //    appSecret: "");
19  
20         //OAuthWebSecurity.RegisterGoogleClient();
21     }
22 }

你必須反注冊這些代碼,以便使用外部的客戶證書。你只需反注冊你想納入你的網站的提供方。對本教程,你只要啟用Facebook證書。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
05         //OAuthWebSecurity.RegisterMicrosoftClient(
06         //    clientId: "",
07         //    clientSecret: "");
08  
09         //OAuthWebSecurity.RegisterTwitterClient(
10         //    consumerKey: "",
11         //    consumerSecret: "");
12  
13         OAuthWebSecurity.RegisterFacebookClient(
14             appId: "",
15             appSecret: "");
16  
17         //OAuthWebSecurity.RegisterGoogleClient();       
18     }
19 }

注意上面的例子,方法包含了注冊參數的空字符串。如果你想現在運行這個應用,應用會拋出一個參數異常,因為這個參數不允許空字符串。為了給出合法的值,你必須像下一節顯示的那樣,在外部提供方注冊你的網站。

 

在外部提供方注冊

要通過來自外部提供方的證書鑒定用戶,你必須在提供方注冊你的網站。當你注冊你的網站時,你將會收到一些參數(比如key或id,以及密碼),以便注冊客戶時包含進去。你必須在你想使用的提供方有一個帳號。

本教程沒有呈現出在這些提供方進行注冊的所有必須的操作步驟。這些步驟通常是不難的。為了成功的注冊你的網站,按照那些網站提供的指示去做。要開始注冊你的網站,看看這些開發者網站:

在Facebook注冊你的網站時,你可以規定"localhost"為網站域名,"http://localhost/"為網址,像下面圖片顯示的那樣。使用localhost對大多數提供方有效,但目前對Microsoft提供方無效。對Microsoft提供方,你必須包含一個合法的web網站地址。

register site

在前面的圖片中,app id,app secret 和contact email的值被剔除了。當你真正注冊你的網站時,那些值將會顯現。你要注意app id 和app secret的值,因為你將會把它們加到你的應用,

創建測試用戶

如果你不介意使用一個已存在的Facebook帳號來測試你的網站,你可以跳過本節。

你能很容易的在Facebook app管理頁面中,為你的應用創建測試用戶。你能用這些測試帳號登錄你的網站。創建測試用戶要點擊左邊導航格子的Roles鏈接,並點擊Create鏈接。

create test users

Facebook網站自動創建你申請的數目的測試帳號。

給應用添加來自提供方的id與secret

現在你收到了來自Facebook的id和secret,回到AuthConfig文件把它們作為參數值增加進去。下面顯示的數值不是真實的數值。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
05         //OAuthWebSecurity.RegisterMicrosoftClient(
06         //    clientId: "",
07         //    clientSecret: "");
08  
09         //OAuthWebSecurity.RegisterTwitterClient(
10         //    consumerKey: "",
11         //    consumerSecret: "");
12  
13         OAuthWebSecurity.RegisterFacebookClient(
14             appId: "111111111111111",
15             appSecret: "a1a1aa111111111a111a111aaa111111");
16  
17         //OAuthWebSecurity.RegisterGoogleClient();
18     }
19 }

 

用外部證書登錄

那就是在你的網站啟用外部證書全部要做的。運行你的應用點擊右上角的login鏈接。模版自動識別出你注冊了Facebook作為提供方,並為這個提供方包含了一個按鈕。如果你注冊了多個提供方,一個按鈕對應一個會自動包括進來。

external login

本教程沒有覆蓋怎樣為外部提供方客制化登錄按鈕。需要那些信息,可以看使用OAuth/OpenID時客制化登錄界面。

點擊Facebook按鈕以Facebook證書登錄。當你選擇了外部提供方的一個,你將被重定向到那個網站,並在其服務提示下登錄。

下圖顯示了Facebook的登錄界面。它標明你在用名為oauthmvcexample的Facebook帳號登錄一個網站。

facebook authentication

用Facebook證書登錄以后,一個頁面告訴用戶這個網站將訪問其基本的信息。

request permission

選擇 Go to App以后, 用戶必須在該網站注冊。下圖顯示了一個用戶用Facebook證書登錄以后的注冊頁面。用戶名被典型的用一個來自提供方的名字預填充。

register

點擊 Register 完成注冊。關閉瀏覽器。

你可以看到新的帳號已經被加到你的數據庫。在Server Explorer里,打開DefaultConnection數據庫並打開Tables目錄。

database tables

右擊 UserProfile 表選擇 Show Table Data

show data

你將看到你增加的新帳號。看看webpage_OAuthMembership表中的數據。你會看到為你剛增加的帳號,有關外部提供方的的更多數據。

如果你只是想啟用外部鑒權,你已經完成了。然而你可以進一步將來自提供方的信息集成進新用戶注冊過程,就像下面幾節顯示的那樣。

為附加的用戶信息創建模型

正如你在前面幾節注意到的,你不需要獲得任何附加的信息來使內建的注冊去工作。但是,大多數提供方返回了關於用戶的附加信息。下面幾節顯示了怎樣保留該信息並將它存入數據庫。特別的,你將保留這些值,用戶的全名,用戶個人主頁的URI,以及表明Facebook是否驗證了該帳號的一個值。

你將使用代碼首先遷移來增加一個表,以便存儲附加用戶信息。你在增加表到已存在的數據庫,因此首先你需要創建一個當前數據庫的快照。通過創建當前數據庫的快照,你可以以后創建一個僅包含新增表的遷移。要創建當前數據庫快照:

  1. 打開 Package Manager Console
  2. 運行命令 enable-migrations
  3. 運行命令 add-migration initial –IgnoreChanges
  4. 運行命令 update-database

 

現在你要增加新的屬性。在Models目錄,打開AccountModels.cs文件,找到RegisterExternalLoginModel類。RegisterExternalLoginModel類持有由鑒權提供方返回的數值。增加名為FullName 與 Link的屬性,像下面突出的那樣。

01 public class RegisterExternalLoginModel
02 {
03     [Required]
04     [Display(Name = "User name")]
05     public string UserName { getset; }
06  
07     public string ExternalLoginData { getset; }
08  
09     [Display(Name = "Full name")]
10     public string FullName { getset; }
11  
12     [Display(Name = "Personal page link")]
13     public string Link { getset; }
14 }

同樣在AccountModels.cs, 增加一個名為ExtraUserInformation的新類。這個類代表了將在數據庫創建的新表。

1 [Table("ExtraUserInformation")]
2 public class ExternalUserInformation
3 {
4     public int Id { getset; }
5     public int UserId { getset; }
6     public string FullName { getset; }
7     public string Link { getset; }
8     public bool? Verified { getset; }
9 }

在UsersContext類里,增加下面突出的代碼,為新類創建一個DbSet屬性。

01 public class UsersContext : DbContext
02 {
03     public UsersContext()
04         base("DefaultConnection")
05     {
06     }
07  
08     public DbSet<UserProfile> UserProfiles { getset; }
09     public DbSet<ExternalUserInformation> ExternalUsers { getset; }
10 }

現在你准備好創建新表了。再次打開 Package Manager Console,這次:

  1. 運行命令 add-migration AddExtraUserInformation
  2. 運行命令 update-database

新表現在在數據庫出現了。

取得附加的數據

有兩個方法獲得附加的用戶數據。第一個是保留返回的用戶數據,默認是在鑒權請求的過程中。第二個方法是特定的調用提供方的 API並請求更多的信息。FullName 與 Link的值自動被Facebook返回。Facebook是否已驗證帳號的一個表示數值,是通過一次對Facebook API的調用獲得的。首先你要為FullName 和 Link填充值,在此之后,你會得到驗證的值。

為了獲得額外的用戶數據, 打開在Controllers 目錄的 AccountController.cs 文件。

這個文件包含了登錄、注冊以及管理帳號的邏輯。特別的,注意名為ExternalLoginCallbackExternalLoginConfirmation的方法。在這些方法內,你為你的應用可增加客制化的外部登錄操作代碼。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"newRegisterExternalLoginModel
2 {
3     UserName = result.UserName,
4     ExternalLoginData = loginData
5 });

替換為這行:

1 return View("ExternalLoginConfirmation"new RegisterExternalLoginModel
2 {
3     UserName = result.UserName,
4     ExternalLoginData = loginData,
5     FullName = result.ExtraData["name"],
6     Link = result.ExtraData["link"]
7 });

這個修改只是包括了FullName 與 Link屬性的值。

ExternalLoginConfirmation 方法里,像下面突出顯示的那樣修改代碼,以便保存附加的用戶信息。

01 if (user == null)
02 {
03     // Insert name into the profile table
04     UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
05     db.SaveChanges();
06  
07     db.ExternalUsers.Add(newExternalUserInformation
08     {
09         UserId = newUser.UserId,
10         FullName = model.FullName,
11         Link = model.Link
12     });
13     db.SaveChanges();
14  
15     OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
16     OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
17  
18     return RedirectToLocal(returnUrl);
19 }
20 else
21 {
22     ModelState.AddModelError("UserName""User name already exists. Please enter a different user name.");
23 }

調整視圖

你從提供方獲得的附加的用戶數據將被顯示於注冊頁面。

在  ViewsAccount 目錄,打開  ExternalLoginConfirmation.cshtml。在已存在的user name字段下面,增加FullName, Link, 和 PictureLink字段。
1 <li>
2     @Html.LabelFor(m => m.FullName)
3     @Html.TextBoxFor(m => m.FullName)
4 </li>
5 <li>
6     @Html.LabelFor(m => m.Link)
7     @Html.TextBoxFor(m => m.Link)
8 </li>

現在你幾乎已經准備好運行應用,並且用保存的附加信息注冊一個新用戶。你必須有一個尚未在該網站注冊的帳號。你可以使用一個不同的測試帳號,也可以刪除UserProfilewebpages_OAuthMembership 表中的你想重新使用的帳號對應行。通過刪除那些行,你能確保該帳號能再次注冊。

運行應用並注冊新用戶。注意這次確認頁面包含了更多的數值。

register

完成注冊以后,關閉瀏覽器。看看數據庫,留心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。

install 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帳號登錄時會運行。

01 [AllowAnonymous]
02 public ActionResult ExternalLoginCallback(string returnUrl)
03 {
04     AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
05         Url.Action("ExternalLoginCallback"new { ReturnUrl = returnUrl }));
06     if (!result.IsSuccessful)
07     {
08         return RedirectToAction("ExternalLoginFailure");
09     }
10  
11     if (result.ExtraData.Keys.Contains("accesstoken"))
12     {
13         Session["facebooktoken"] = result.ExtraData["accesstoken"];
14     }
15  
16     if (OAuthWebSecurity.Login(
17         result.Provider,
18         result.ProviderUserId,
19         createPersistentCookie: false))
20     {
21         return RedirectToLocal(returnUrl);
22     }
23  
24     if (User.Identity.IsAuthenticated)
25     {
26         // If the current user is logged in add the new account
27         OAuthWebSecurity.CreateOrUpdateAccount(
28             result.Provider,
29             result.ProviderUserId,
30             User.Identity.Name);
31         return RedirectToLocal(returnUrl);
32     }
33     else
34     {
35         // User is new, ask for their desired membership name
36         string loginData = OAuthWebSecurity.SerializeProviderUserId(
37             result.Provider,
38             result.ProviderUserId);
39         ViewBag.ProviderDisplayName =
40             OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
41         ViewBag.ReturnUrl = returnUrl;
42         return View("ExternalLoginConfirmation"new RegisterExternalLoginModel
43         {
44             UserName = result.UserName,
45             ExternalLoginData = loginData,
46             FullName = result.ExtraData["name"],
47             Link = result.ExtraData["link"]
48         });   
49     }
50 }

盡管這個例子從Facebook獲得了一個access token,你可以通過同樣的名為“accesstoken”的關鍵字從任何外部提供方獲得access token。

為了防止令牌在用戶已退出登錄以后仍然保持,你可以添加如下突出的代碼到AccountController中的 LogOff方法。

1 [HttpPost]
2 [ValidateAntiForgeryToken]
3 public ActionResult LogOff()
4 {
5     WebSecurity.Logout();
6     Session.Remove("facebooktoken");
7  
8     return RedirectToAction("Index""Home");
9 }

獲得需要訪問令牌的用戶信息

現在你已經保存了access token並且安裝了Facebook C# SDK包,你可以一起使用它們去從Facebook請求附加的用戶信息。在ExternalLoginConfirmation方法中,通過傳遞access token的值創建了一個FacebookClient類的實例。請求當前鑒權用戶的verified屬性值。verified屬性表明了Facebook是否已經通過一些其他的方法,比如給蜂窩電話發送一個信息,驗證了該帳號。將這個數值保存進數據庫。

01 if (user == null)
02 {
03     // Insert name into the profile table
04     UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
05     db.SaveChanges();
06  
07     bool facebookVerified;
08  
09     var client = new Facebook.FacebookClient(Session["facebooktoken"].ToString());
10     dynamic response = client.Get("me"new { fields = "verified" });
11     if (response.ContainsKey("verified"))
12     {
13         facebookVerified = response["verified"];
14     }
15     else
16     {
17         facebookVerified = false;
18     }
19  
20     db.ExternalUsers.Add(newExternalUserInformation
21     {
22         UserId = newUser.UserId,
23         FullName = model.FullName,
24         Link = model.Link,
25         Verified = facebookVerified
26     });
27     db.SaveChanges();
28  
29     OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
30     OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
31  
32     return RedirectToLocal(returnUrl);
33 }

你將需要再一次或者刪除數據庫中用戶的記錄,或者使用一個不同的Facebook帳號。

運行應用,並且注冊新用戶。看看ExtraUserInformation表 Verified屬性的值。

總結

本教程中,你創建了集成Facebook來進行用戶鑒權並注冊數據的網站。你學習了MVC4 web應用創立的默認的行為,以及如何客制化那個默認的行為。

ASP.NET MVC 4 使用 OAuth

這個教程向你展示了如何創建一個ASP.NET MVC 4的web應用,能讓用戶用外部提供方的證書(比如Facebook, Twitter, Microsoft,或Google)登陸,然后將源自那些提供方的一些功能集成進你的web應用。為簡單起見,本教程主要講述與Facebook的證書一起工作。

在你的web應用中啟用這些證書提供了一個重要的優勢,因為數百萬用戶已經有這些外部提供方的帳號。如果不是必須創建並且記住一組新的證書,這些用戶可能更傾向於注冊你的網站。而且當一個用戶通過某一個提供方登陸以后,你可以引入提供方的社會化動作。

你將需要構建的

本指南主要有兩個目標:

  1. 使用戶可以通過開放授權服務者提供的憑據登錄
  2. 從第三方獲取賬號信息並通過在你的站點上完善賬戶信息

雖然本文的例子只演示了將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中任意一個。

create project

在 New ASP.NET MVC 4 Project 窗口, 選擇 Internet Application 並保留 Razor 作為視圖引擎。

select Internet Application

啟用一個提供者

當你用Internet Application模板創建出一個MVC 4 web application時,這個工程在App_Start目錄創建了一個名為AuthConfig.cs的文件。

AuthConfig file

AuthConfig文件包含了針對外部證書提供方的客戶注冊代碼。默認情況下,這些代碼被注釋掉了,所以沒有外部提供者被啟用。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
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
07  
08         //OAuthWebSecurity.RegisterMicrosoftClient(
09         //    clientId: "",
10         //    clientSecret: "");
11  
12         //OAuthWebSecurity.RegisterTwitterClient(
13         //    consumerKey: "",
14         //    consumerSecret: "");
15  
16         //OAuthWebSecurity.RegisterFacebookClient(
17         //    appId: "",
18         //    appSecret: "");
19  
20         //OAuthWebSecurity.RegisterGoogleClient();
21     }
22 }

你必須反注冊這些代碼,以便使用外部的客戶證書。你只需反注冊你想納入你的網站的提供方。對本教程,你只要啟用Facebook證書。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
05         //OAuthWebSecurity.RegisterMicrosoftClient(
06         //    clientId: "",
07         //    clientSecret: "");
08  
09         //OAuthWebSecurity.RegisterTwitterClient(
10         //    consumerKey: "",
11         //    consumerSecret: "");
12  
13         OAuthWebSecurity.RegisterFacebookClient(
14             appId: "",
15             appSecret: "");
16  
17         //OAuthWebSecurity.RegisterGoogleClient();       
18     }
19 }

注意上面的例子,方法包含了注冊參數的空字符串。如果你想現在運行這個應用,應用會拋出一個參數異常,因為這個參數不允許空字符串。為了給出合法的值,你必須像下一節顯示的那樣,在外部提供方注冊你的網站。

 

在外部提供方注冊

要通過來自外部提供方的證書鑒定用戶,你必須在提供方注冊你的網站。當你注冊你的網站時,你將會收到一些參數(比如key或id,以及密碼),以便注冊客戶時包含進去。你必須在你想使用的提供方有一個帳號。

本教程沒有呈現出在這些提供方進行注冊的所有必須的操作步驟。這些步驟通常是不難的。為了成功的注冊你的網站,按照那些網站提供的指示去做。要開始注冊你的網站,看看這些開發者網站:

在Facebook注冊你的網站時,你可以規定"localhost"為網站域名,"http://localhost/"為網址,像下面圖片顯示的那樣。使用localhost對大多數提供方有效,但目前對Microsoft提供方無效。對Microsoft提供方,你必須包含一個合法的web網站地址。

register site

在前面的圖片中,app id,app secret 和contact email的值被剔除了。當你真正注冊你的網站時,那些值將會顯現。你要注意app id 和app secret的值,因為你將會把它們加到你的應用,

創建測試用戶

如果你不介意使用一個已存在的Facebook帳號來測試你的網站,你可以跳過本節。

你能很容易的在Facebook app管理頁面中,為你的應用創建測試用戶。你能用這些測試帳號登錄你的網站。創建測試用戶要點擊左邊導航格子的Roles鏈接,並點擊Create鏈接。

create test users

Facebook網站自動創建你申請的數目的測試帳號。

給應用添加來自提供方的id與secret

現在你收到了來自Facebook的id和secret,回到AuthConfig文件把它們作為參數值增加進去。下面顯示的數值不是真實的數值。

01 public static class AuthConfig
02 {
03     public static void RegisterAuth()
04     {
05         //OAuthWebSecurity.RegisterMicrosoftClient(
06         //    clientId: "",
07         //    clientSecret: "");
08  
09         //OAuthWebSecurity.RegisterTwitterClient(
10         //    consumerKey: "",
11         //    consumerSecret: "");
12  
13         OAuthWebSecurity.RegisterFacebookClient(
14             appId: "111111111111111",
15             appSecret: "a1a1aa111111111a111a111aaa111111");
16  
17         //OAuthWebSecurity.RegisterGoogleClient();
18     }
19 }

 

用外部證書登錄

那就是在你的網站啟用外部證書全部要做的。運行你的應用點擊右上角的login鏈接。模版自動識別出你注冊了Facebook作為提供方,並為這個提供方包含了一個按鈕。如果你注冊了多個提供方,一個按鈕對應一個會自動包括進來。

external login

本教程沒有覆蓋怎樣為外部提供方客制化登錄按鈕。需要那些信息,可以看使用OAuth/OpenID時客制化登錄界面。

點擊Facebook按鈕以Facebook證書登錄。當你選擇了外部提供方的一個,你將被重定向到那個網站,並在其服務提示下登錄。

下圖顯示了Facebook的登錄界面。它標明你在用名為oauthmvcexample的Facebook帳號登錄一個網站。

facebook authentication

用Facebook證書登錄以后,一個頁面告訴用戶這個網站將訪問其基本的信息。

request permission

選擇 Go to App以后, 用戶必須在該網站注冊。下圖顯示了一個用戶用Facebook證書登錄以后的注冊頁面。用戶名被典型的用一個來自提供方的名字預填充。

register

點擊 Register 完成注冊。關閉瀏覽器。

你可以看到新的帳號已經被加到你的數據庫。在Server Explorer里,打開DefaultConnection數據庫並打開Tables目錄。

database tables

右擊 UserProfile 表選擇 Show Table Data

show data

你將看到你增加的新帳號。看看webpage_OAuthMembership表中的數據。你會看到為你剛增加的帳號,有關外部提供方的的更多數據。

如果你只是想啟用外部鑒權,你已經完成了。然而你可以進一步將來自提供方的信息集成進新用戶注冊過程,就像下面幾節顯示的那樣。

為附加的用戶信息創建模型

正如你在前面幾節注意到的,你不需要獲得任何附加的信息來使內建的注冊去工作。但是,大多數提供方返回了關於用戶的附加信息。下面幾節顯示了怎樣保留該信息並將它存入數據庫。特別的,你將保留這些值,用戶的全名,用戶個人主頁的URI,以及表明Facebook是否驗證了該帳號的一個值。

你將使用代碼首先遷移來增加一個表,以便存儲附加用戶信息。你在增加表到已存在的數據庫,因此首先你需要創建一個當前數據庫的快照。通過創建當前數據庫的快照,你可以以后創建一個僅包含新增表的遷移。要創建當前數據庫快照:

  1. 打開 Package Manager Console
  2. 運行命令 enable-migrations
  3. 運行命令 add-migration initial –IgnoreChanges
  4. 運行命令 update-database

 

現在你要增加新的屬性。在Models目錄,打開AccountModels.cs文件,找到RegisterExternalLoginModel類。RegisterExternalLoginModel類持有由鑒權提供方返回的數值。增加名為FullName 與 Link的屬性,像下面突出的那樣。

01 public class RegisterExternalLoginModel
02 {
03     [Required]
04     [Display(Name = "User name")]
05     public string UserName { getset; }
06  
07     public string ExternalLoginData { getset; }
08  
09     [Display(Name = "Full name")]
10     public string FullName { getset; }
11  
12     [Display(Name = "Personal page link")]
13     public string Link { getset; }
14 }

同樣在AccountModels.cs, 增加一個名為ExtraUserInformation的新類。這個類代表了將在數據庫創建的新表。

1 [Table("ExtraUserInformation")]
2 public class ExternalUserInformation
3 {
4     public int Id { getset; }
5     public int UserId { getset; }
6     public string FullName { getset; }
7     public string Link { getset; }
8     public bool? Verified { getset; }
9 }

在UsersContext類里,增加下面突出的代碼,為新類創建一個DbSet屬性。

01 public class UsersContext : DbContext
02 {
03     public UsersContext()
04         base("DefaultConnection")
05     {
06     }
07  
08     public DbSet<UserProfile> UserProfiles { getset; }
09     public DbSet<ExternalUserInformation> ExternalUsers { getset; }
10 }

現在你准備好創建新表了。再次打開 Package Manager Console,這次:

  1. 運行命令 add-migration AddExtraUserInformation
  2. 運行命令 update-database

新表現在在數據庫出現了。

取得附加的數據

有兩個方法獲得附加的用戶數據。第一個是保留返回的用戶數據,默認是在鑒權請求的過程中。第二個方法是特定的調用提供方的 API並請求更多的信息。FullName 與 Link的值自動被Facebook返回。Facebook是否已驗證帳號的一個表示數值,是通過一次對Facebook API的調用獲得的。首先你要為FullName 和 Link填充值,在此之后,你會得到驗證的值。

為了獲得額外的用戶數據, 打開在Controllers 目錄的 AccountController.cs 文件。

這個文件包含了登錄、注冊以及管理帳號的邏輯。特別的,注意名為ExternalLoginCallbackExternalLoginConfirmation的方法。在這些方法內,你為你的應用可增加客制化的外部登錄操作代碼。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"newRegisterExternalLoginModel
2 {
3     UserName = result.UserName,
4     ExternalLoginData = loginData
5 });

替換為這行:

1 return View("ExternalLoginConfirmation"new RegisterExternalLoginModel
2 {
3     UserName = result.UserName,
4     ExternalLoginData = loginData,
5     FullName = result.ExtraData["name"],
6     Link = result.ExtraData["link"]
7 });

這個修改只是包括了FullName 與 Link屬性的值。

ExternalLoginConfirmation 方法里,像下面突出顯示的那樣修改代碼,以便保存附加的用戶信息。

01 if (user == null)
02 {
03     // Insert name into the profile table
04     UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
05     db.SaveChanges();
06  
07     db.ExternalUsers.Add(newExternalUserInformation
08     {
09         UserId = newUser.UserId,
10         FullName = model.FullName,
11         Link = model.Link
12     });
13     db.SaveChanges();
14  
15     OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
16     OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
17  
18     return RedirectToLocal(returnUrl);
19 }
20 else
21 {
22     ModelState.AddModelError("UserName""User name already exists. Please enter a different user name.");
23 }

調整視圖

你從提供方獲得的附加的用戶數據將被顯示於注冊頁面。

在  ViewsAccount 目錄,打開  ExternalLoginConfirmation.cshtml。在已存在的user name字段下面,增加FullName, Link, 和 PictureLink字段。
1 <li>
2     @Html.LabelFor(m => m.FullName)
3     @Html.TextBoxFor(m => m.FullName)
4 </li>
5 <li>
6     @Html.LabelFor(m => m.Link)
7     @Html.TextBoxFor(m => m.Link)
8 </li>

現在你幾乎已經准備好運行應用,並且用保存的附加信息注冊一個新用戶。你必須有一個尚未在該網站注冊的帳號。你可以使用一個不同的測試帳號,也可以刪除UserProfilewebpages_OAuthMembership 表中的你想重新使用的帳號對應行。通過刪除那些行,你能確保該帳號能再次注冊。

運行應用並注冊新用戶。注意這次確認頁面包含了更多的數值。

register

完成注冊以后,關閉瀏覽器。看看數據庫,留心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。

install 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帳號登錄時會運行。

01 [AllowAnonymous]
02 public ActionResult ExternalLoginCallback(string returnUrl)
03 {
04     AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
05         Url.Action("ExternalLoginCallback"new { ReturnUrl = returnUrl }));
06     if (!result.IsSuccessful)
07     {
08         return RedirectToAction("ExternalLoginFailure");
09     }
10  
11     if (result.ExtraData.Keys.Contains("accesstoken"))
12     {
13         Session["facebooktoken"] = result.ExtraData["accesstoken"];
14     }
15  
16     if (OAuthWebSecurity.Login(
17         result.Provider,
18         result.ProviderUserId,
19         createPersistentCookie: false))
20     {
21         return RedirectToLocal(returnUrl);
22     }
23  
24     if (User.Identity.IsAuthenticated)
25     {
26         // If the current user is logged in add the new account
27         OAuthWebSecurity.CreateOrUpdateAccount(
28             result.Provider,
29             result.ProviderUserId,
30             User.Identity.Name);
31         return RedirectToLocal(returnUrl);
32     }
33     else
34     {
35         // User is new, ask for their desired membership name
36         string loginData = OAuthWebSecurity.SerializeProviderUserId(
37             result.Provider,
38             result.ProviderUserId);
39         ViewBag.ProviderDisplayName =
40             OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
41         ViewBag.ReturnUrl = returnUrl;
42         return View("ExternalLoginConfirmation"new RegisterExternalLoginModel
43         {
44             UserName = result.UserName,
45             ExternalLoginData = loginData,
46             FullName = result.ExtraData["name"],
47             Link = result.ExtraData["link"]
48         });   
49     }
50 }

盡管這個例子從Facebook獲得了一個access token,你可以通過同樣的名為“accesstoken”的關鍵字從任何外部提供方獲得access token。

為了防止令牌在用戶已退出登錄以后仍然保持,你可以添加如下突出的代碼到AccountController中的 LogOff方法。

1 [HttpPost]
2 [ValidateAntiForgeryToken]
3 public ActionResult LogOff()
4 {
5     WebSecurity.Logout();
6     Session.Remove("facebooktoken");
7  
8     return RedirectToAction("Index""Home");
9 }

獲得需要訪問令牌的用戶信息

現在你已經保存了access token並且安裝了Facebook C# SDK包,你可以一起使用它們去從Facebook請求附加的用戶信息。在ExternalLoginConfirmation方法中,通過傳遞access token的值創建了一個FacebookClient類的實例。請求當前鑒權用戶的verified屬性值。verified屬性表明了Facebook是否已經通過一些其他的方法,比如給蜂窩電話發送一個信息,驗證了該帳號。將這個數值保存進數據庫。

01 if (user == null)
02 {
03     // Insert name into the profile table
04     UserProfile newUser = db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
05     db.SaveChanges();
06  
07     bool facebookVerified;
08  
09     var client = new Facebook.FacebookClient(Session["facebooktoken"].ToString());
10     dynamic response = client.Get("me"new { fields = "verified" });
11     if (response.ContainsKey("verified"))
12     {
13         facebookVerified = response["verified"];
14     }
15     else
16     {
17         facebookVerified = false;
18     }
19  
20     db.ExternalUsers.Add(newExternalUserInformation
21     {
22         UserId = newUser.UserId,
23         FullName = model.FullName,
24         Link = model.Link,
25         Verified = facebookVerified
26     });
27     db.SaveChanges();
28  
29     OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
30     OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
31  
32     return RedirectToLocal(returnUrl);
33 }

你將需要再一次或者刪除數據庫中用戶的記錄,或者使用一個不同的Facebook帳號。

運行應用,並且注冊新用戶。看看ExtraUserInformation表 Verified屬性的值。

總結

本教程中,你創建了集成Facebook來進行用戶鑒權並注冊數據的網站。你學習了MVC4 web應用創立的默認的行為,以及如何客制化那個默認的行為。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM