共用方式為


建立一個 ASP.NET MVC 5 應用程式,支援 Facebook、Twitter、LinkedIn 及 Google OAuth2 登入(C#)

作者 :瑞克·安德森

本教學將展示如何打造一個 ASP.NET MVC 5 網頁應用程式,讓使用者能使用外部認證提供者(如 Facebook、Twitter、LinkedIn、Microsoft 或 Google)的憑證登入 OAuth 2.0 。 為了簡化,這個教學重點是使用 Facebook 和 Google 的憑證。

在您的網站上啟用這些憑證,帶來顯著優勢,因為數百萬用戶已在這些外部服務提供商擁有帳號。 如果這些使用者不必建立並記住一組新的憑證,他們可能更願意註冊你的網站。

另見 ASP.NET MVC 5 應用程式中的 SMS 與電子郵件雙因素驗證

教學也展示了如何為使用者新增個人資料資料,以及如何使用會員 API 新增角色。 這個教學由 Rick Anderson 撰寫(請在 Twitter 上追蹤我: @RickAndMSFT )。

使用者入門

首先安裝並執行 Visual Studio Express 2013 for Web 或Visual Studio 2013。 安裝 Visual Studio 2013 更新 3 或更高版本。

備註

你必須安裝 Visual Studio 2013 更新版 3 或更新版本,才能使用 Google OAuth 2 並在本地除錯而不會觸發 SSL 警告。

開始頁面點選新專案,或是使用選單選擇「檔案」,然後再選擇「新專案」。

顯示 Visual Studio 開始頁面的截圖。

建立你的第一個應用程式

點選 新專案,然後在左側選擇 Visual C# ,再選 網頁ASP.NET 再選擇網頁應用程式。 將專案命名為「MvcAuth」,然後點擊 確定

顯示 Visual Studio 新專案選單頁面的截圖。在名稱文字欄位輸入 M v c Auth。

新 ASP.NET 專案 對話框中,點擊 MVC。 如果驗證不是 個人使用者帳號,請點擊 變更驗證 按鈕並選擇 個人使用者帳號。 選擇 雲端中的 Host,應用程式會更容易在 Azure 上架設。

顯示新 A S P 點 NET 專案對話框的截圖。「變更認證」按鈕和「雲端主機」勾選框會被標示出來。

如果你選擇雲端 主機,請完成設定對話框。

顯示「配置 Microsoft Azure 網站」對話框的截圖。輸入範例資料庫密碼。

使用 NuGet 更新到最新的 OWIN 中介軟體

使用 NuGet 套件管理器來更新 OWIN 中介軟體。 在左側選單選擇 更新 。 你可以點擊 「全部更新 」按鈕,或只搜尋 OWIN 套件(如下張圖片所示):

顯示「管理 Nu GET 套件」對話框的截圖。更新列和全部更新按鈕會被高亮顯示。

下圖僅顯示 OWIN 套件:

顯示「管理 Nu GET 套件」對話框的截圖。更新欄和搜尋欄(輸入 OWN)會被高亮顯示。

你可以在套件管理主控台(PMC)輸入 Update-Package 指令,更新所有套件。

F5Ctrl+F5 即可執行該應用程式。 下方圖片中的埠號為 1234。 當你執行應用程式時,你會看到不同的埠號。

根據瀏覽器視窗大小,您可能需要點擊導覽圖示,才能看到 首頁關於聯絡註冊登入 連結。

顯示 My A S P dot NET 首頁的截圖。導航圖示會被高亮顯示。
顯示 My A S P dot NET 首頁的截圖。導航圖示會被高亮並選取,顯示一個下拉選單和導航連結。

在專案中設定 SSL

要連接像 Google 和 Facebook 這樣的認證服務提供者,你需要設定使用 SSL IIS-Express。 登入後繼續使用 SSL 很重要,不要降級到 HTTP。你的登入 Cookie 與使用者名稱和密碼都屬於一樣重要的秘密,若未使用 SSL,則是在以明文形式傳輸。 況且,你在 MVC 管線執行之前已經花時間進行握手並保護通道安全(這是 HTTPS 比 HTTP 慢的主要原因),所以在登入後再切換回 HTTP 進行重新導向,不會讓目前的請求或未來的請求變得更快。

  1. 解決方案檔案總管中,點選 MvcAuth 專案。

  2. 按 F4 鍵即可顯示專案屬性。 或者,從 檢視 選單中你可以選擇 屬性視窗

  3. SSL 啟用 改為 true。

    這張截圖顯示了 M v c Auth 專案的解決方案總管專案屬性。S S L 啟用 True 和 S S L U R L 被標示出來。

  4. 複製 SSL URL (這個 URL 預設為 https://localhost:44300/,除非您建立了其他 SSL 專案)。

  5. 解決方案總管中,右鍵點選 MvcAuth 專案並選擇 屬性

  6. 選擇 網頁 分頁,然後將 SSL URL 貼上到 專案網址 框中。 儲存檔案(Ctl+S)。 你需要這個網址來設定 Facebook 和 Google 的認證應用程式。

    截圖顯示 M v c Auth 專案的屬性頁面。左側選單的網頁標籤和貼在 Project U R L 框裡的 S S L U R L 都會被高亮標示。

  7. 在控制器上新增 RequireHttps 屬性 Home ,要求所有請求都必須使用 HTTPS。 更安全的做法是將 RequireHttps 過濾器加到應用程式中。 請參閱我教學中「用 SSL 和授權屬性保護應用程式」的章節,「 建立一個 ASP.NET MVC 應用程式,搭配認證和 SQL DB,部署到 Azure App Service」。 Home 控制器的部分內容如下所示。

    [RequireHttps]
    public class HomeController : Controller
    {
       public ActionResult Index()
       {
          return View();
       }
    
  8. 按 CTRL+F5 執行應用程式。 如果你之前已經安裝過該憑證,可以跳過本節剩下的部分,直接跳到 「為 OAuth 2 建立 Google 應用程式並將應用程式與專案連結」,否則,請依照指示信任 IIS Express 產生的自簽憑證。

    截圖顯示 Visual Studio 的對話框提示使用者選擇是否信任 I I S Express S S L 憑證。

  9. 閱讀 安全警告 對話框,然後點 選「是 」以安裝代表 localhost 的憑證。

    截圖顯示 Visual Studio 安全警告對話框,提示使用者選擇是否安裝認證。

  10. IE 瀏覽器顯示 首頁,且沒有 SSL 警告。

    截圖顯示 My A S P dot NET 首頁,沒有 S S L 警告。

  11. Google Chrome 也接受該憑證,並會無警告地顯示 HTTPS 內容。 Firefox 使用自己的憑證儲存庫,因此會顯示警告。 您可以放心點擊 「我了解風險」來申請我們的申請。

    截圖顯示 My A S P dot NET 應用程式在 Firefox 上運行。一個不信任連線警告頁面正在詢問使用者是否接受該應用程式並繼續進行。

為 OAuth 2 建立 Google 應用程式並將該應用程式與專案連結

警告

關於目前 Google OAuth 的說明,請參見 在 ASP.NET Core 中設定 Google 認證

  1. 進入 Google 開發者主控台

  2. 如果你之前沒建立過專案,請在左側分頁選擇 憑證 ,然後選擇 建立

  3. 在左側分頁,點選 憑證

  4. 點選 建立憑證 ,然後點選 OAuth 客戶端 ID

    1. 「建立用戶端 ID 」對話框中,保留該應用程式類型的預設 網頁應用程式
    2. 請將 授權的 JavaScript 來源設定為你上面使用的 SSL URL(https://localhost:44300/ 除非你有建立其他 SSL 專案)。
    3. 授權重定向 URI 設定為:
      https://localhost:44300/signin-google
  5. 點選 OAuth 同意畫面選單項目,然後設定您的電子郵件地址和產品名稱。 填寫表單後,點擊 儲存

  6. 點選函式庫選單項目,搜尋 Google+ API,點進去,然後按下啟用。

    截圖顯示搜尋結果列表。Google 加上 A P I 的搜尋結果會被標示出來。

    下圖顯示已啟用的 API。

    截圖顯示 Google 開發者控制台頁面列出了已啟用的 A P I 列表。當 A P I 旁邊出現綠色 ON 按鈕時,該 A P I 顯示為已啟用。

  7. 從 Google API API Manager 中,請造訪 憑證 標籤以取得 用戶端 ID。 下載以儲存帶有應用程式秘密的 JSON 檔案。 將 ClientIDClientSecret 複製並貼上到 UseGoogleAuthenticationApp_Start 資料夾裡 Startup.Auth.cs 檔案中找到的方法。 下方顯示的 ClientIDClientSecret 值是範例,無法正常運作。

    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    
        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });
        
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    
        // Uncomment the following lines to enable logging in with third party login providers
        //app.UseMicrosoftAccountAuthentication(
        //    clientId: "",
        //    clientSecret: "");
    
        //app.UseTwitterAuthentication(
        //   consumerKey: "",
        //   consumerSecret: "");
    
        //app.UseFacebookAuthentication(
        //   appId: "",
        //   appSecret: "");
    
        app.UseGoogleAuthentication(
             clientId: "000-000.apps.googleusercontent.com",
             clientSecret: "00000000000");
    }
    

    警告

    安全性——切勿在原始碼中儲存敏感資料。 帳號和憑證會加入上方程式碼,以保持範例簡單。 請參閱部署 密碼及其他敏感資料至 ASP.NET 與 Azure App Service 的最佳實務

  8. CTRL+F5 即可建置並執行應用程式。 點擊 登入 連結。

    顯示 My A S P dot NET 首頁的截圖。導航按鈕和登入連結會被高亮顯示。

  9. 「使用其他服務登入」中,點選 Google

    顯示 My A S P dot NET 登入頁面的截圖。「使用其他服務登入」對話框和 Google 按鈕會被高亮亮出。

    備註

    如果你漏掉上述任何步驟,將會收到 HTTP 401 錯誤。 請重看上面的步驟。 如果你漏掉了必須設定(例如 產品名稱),就新增缺少的項目並儲存;認證可能需要幾分鐘才能生效。

  10. 您將被導向至 Google 網站,輸入您的憑證。

    截圖顯示 Google 帳號登入頁面。範例憑證會輸入在文字欄位中。

  11. 輸入憑證後,系統會提示你對剛建立的網頁應用程式授予權限:

    顯示 Google 帳號「請求權限」頁面的截圖,提示使用者取消或接受離線存取網頁應用程式。

  12. 按一下 [接受]。 您現在會被導回 MvcAuth 應用程式的 註冊 頁面,在那裡您可以註冊您的 Google 帳號。 你可以選擇更改 Gmail 帳號使用的本地電子郵件註冊名稱,但通常你會想保留預設的電子郵件別名(也就是你用來驗證的那個)。 按一下 [註冊]

    顯示 My A S P .NET 註冊申請頁面的截圖。在電子郵件文字欄位輸入一個 Google 範例帳號。

在 Facebook 建立應用程式並將應用程式與專案連結

警告

關於目前的 Facebook OAuth2 認證說明,請參見 設定 Facebook 認證

使用伺服器檔案總管檢視會員資料

檢視 選單中,點選 伺服器檔案總管

截圖顯示 Visual Studio 的下拉選單,伺服器檔案總管被高亮顯示。

展開 DefaultConnection (MvcAuth),展開 資料表,右鍵點選 AspNetUsers,然後點選顯示資料表數據

截圖顯示服務總管選單選項。資料連線、預設連線 M 對 c 認證,以及表格分頁也被擴充了。

aspnetusers 表格資料

將個人資料加入使用者類別

在此區塊中,註冊時你會將出生日期和家鄉加入使用者資料,如下圖所示。

登記包含家鄉及生日

打開 Models\IdentityModels.cs 檔案,新增出生日期和家鄉房產:

public class ApplicationUser : IdentityUser
{
    public string HomeTown { get; set; }
    public System.DateTime? BirthDate { get; set; }
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

打開 Models\AccountViewModels.cs 檔案,輸入設定的出生日期和家鄉房產。ExternalLoginConfirmationViewModel

public class ExternalLoginConfirmationViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    public string HomeTown { get; set; }
    public System.DateTime? BirthDate { get; set; }
}

打開 Controllers\AccountController.cs 檔案,並在動作方法中加入出生日期和家鄉 ExternalLoginConfirmation 的代碼,如圖所示:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
    if (User.Identity.IsAuthenticated)
    {
        return RedirectToAction("Manage");
    }

    if (ModelState.IsValid)
    {
        // Get the information about the user from the external login provider
        var info = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return View("ExternalLoginFailure");
        }
        var user = new ApplicationUser() 
        {
            UserName = model.Email, Email = model.Email,
            BirthDate = model.BirthDate,
            HomeTown  = model.HomeTown
        
        };
        IdentityResult result = await UserManager.CreateAsync(user);
        if (result.Succeeded)
        {
            result = await UserManager.AddLoginAsync(user.Id, info.Login);
            if (result.Succeeded)
            {
                await SignInAsync(user, isPersistent: false);
                
                // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
                // Send an email with this link
                // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                // SendEmail(user.Email, callbackUrl, "Confirm your account", "Please confirm your account by clicking this link");
                
                return RedirectToLocal(returnUrl);
            }
        }
        AddErrors(result);
    }

    ViewBag.ReturnUrl = returnUrl;
    return View(model);
}

將出生日期和家鄉資料加入 Views\Account\ExternalLoginConfirmation.cshtml 檔案:

@model MvcAuth.Models.ExternalLoginConfirmationViewModel
@{
    ViewBag.Title = "Register";
}
<h2>@ViewBag.Title.</h2>
<h3>Associate your @ViewBag.LoginProvider account.</h3>

@using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

    <h4>Association Form</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <p class="text-info">
        You've successfully authenticated with <strong>@ViewBag.LoginProvider</strong>.
            Please enter a user name for this site below and click the Register button to finish
            logging in.
    </p>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.HomeTown, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.HomeTown, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.HomeTown)
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.BirthDate, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.BirthDate, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.BirthDate)
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

刪除會員資料庫,以便你可以重新在應用程式中註冊你的 Facebook 帳號,並確認你能夠新增新的出生日期和家鄉等個人檔案資訊。

解決方案總管中,點選「顯示所有檔案」圖示,然後右鍵點擊 Add_Data\aspnet-MvcAuth-dateStamp<>.mdf再點「刪除」。

顯示解決方案總管頁面的截圖。「顯示所有檔案」圖示與 Mvc Auth 會員資格資料庫已標示。

工具 選單中,點選 NuGet 套件管理器,然後點選 套件管理員主控台 (PMC)。 在 PMC 中輸入以下指令。

  1. Enable-Migrations
  2. Add-Migration 開始
  3. Update-Database

啟動應用程式,使用 Facebook 和 Google 登入並註冊一些使用者。

檢視會員資料

檢視 選單中,點選 伺服器檔案總管

顯示 Visual Studio VIEW 下拉選單的截圖。服務檔案總管選項會被高亮顯示。

右鍵點 選 AspNetUsers ,然後點 選「顯示資料表資料」。

這張截圖顯示了伺服器檔案總管選單的選項。A s p Net Users 與「顯示資料表」選項會被標示。

HomeTownBirthDate 欄位如下所示。

顯示 A s p 網路使用者資料表資料的截圖。表格資料顯示 I D、家鄉、出生日期、電子郵件及電子郵件確認欄位。

登出你的應用程式並用其他帳號登入

如果你用 Facebook 登入你的應用程式,然後登出再嘗試用不同的 Facebook 帳號(使用同一瀏覽器)登入,你會立刻登入到你之前使用的 Facebook 帳號。 要使用其他帳號,你需要先進入 Facebook 並登出。 同樣的規則也適用於任何其他第三方驗證服務提供者。 或者,你也可以用不同的瀏覽器登入另一個帳號。

後續步驟

請跟著我的教學「 建立一個 ASP.NET MVC 應用程式,包含認證和 SQL DB,並部署到 Azure App Service」,該教學會延續這個教學並展示以下內容:

  1. 如何將你的應用程式部署到 Azure。
  2. 如何用角色來保障你的應用程式。
  3. 如何用 RequireHttpsAuthorize 篩選器保護你的應用程式。
  4. 如何使用會員 API 來新增使用者和角色。

關於外部認證服務 ASP.NET 如何運作,請參見 Robert McMurray 的 《外部驗證服務》。 Robert 的文章也詳細說明了如何啟用 Microsoft 和 Twitter 的認證。 Tom Dykstra 優秀的 EF/MVC 教學 展示了如何使用 Entity Framework 工作。