The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何在 ASP.NET Web API 2 專案中啟用表單驗證 (Forms Authentication)

使用 Visual Studio 2015 開發 ASP.NET Web API 2 專案時,有好幾種專案範本可以選擇,你可以從「空白」專案範本開始,也可以從「MVC」專案範本開始 (記得勾選 Web API 核心參考),也可以直接從「Web API」專案範本開始,由於專案範本通常夾雜大量的範例程式,很多時候我們並無法在第一時間得知每段程式碼與設定檔的細節,以至於在後續開發的過程發生許多問題。本篇文章將帶大家了解如何成功在 ASP.NET Web API 2 專案正確啟用 ASP.NET 的表單驗證機制 (FormsAuthenticaion)。

針對不同的專案範本,我特別建立了一個可比較的 Git 專案,你只要先複製這個 GitHub 專案回來,就可以比對不同專案範本之間的檔案差異之處。

這邊我寫了一個非常簡單的表單驗證程式碼,程式碼如下:

先建立一個 LoginViewModel

using System.ComponentModel.DataAnnotations;

namespace YourNamespace.Models
{
    public class UserLoginViewModel
    {
        [Required]
        [StringLength(20)]
        public string Username { get; set; }
        [Required]
        public string Password { get; set; }
    }
}

再建立一個 UsersController

using YourNamespace.Models;
using System.Net;
using System.Web.Http;
using System.Web.Security;

namespace YourNamespace.Controllers
{
    [RoutePrefix("user")]
    public class UsersController : ApiController
    {
        [Route("login")]
        public IHttpActionResult PostLogin(UserLoginViewModel user)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest();
            }

            if (user.Username == "admin" && user.Password == "123")
            {
                FormsAuthentication.RedirectFromLoginPage(user.Username, false);
                return StatusCode(HttpStatusCode.NoContent);
            }
            else
            {
                return StatusCode(HttpStatusCode.Unauthorized);
            }
        }

        [Route("logout")]
        [HttpGet][HttpPost]
        public void Logout()
        {
            FormsAuthentication.SignOut();
        }

        [Authorize]
        [Route("profile")]
        public IHttpActionResult GetProfile()
        {
            return Ok(User.Identity.Name);
        }
    }
}

基本上,上述這兩個檔案就可以完成最基本的登入 (PostLogin)、登出 (Logout) 等基本身分驗證功能,搭配 [Authorize] 動作過濾器 (Action Filter) 還可以對 取得登入者名稱 (GetProfile) 功能進行基本授權驗證,因此這是一份完成的表單驗證實作,非常容易上手。

 

以下我將介紹在不同的專案範本下,才能讓這段程式碼正常運作:

1. 使用「空白」專案範本開始,外加 Web API 核心參考 (如下圖示)

這部分只要在專案根目錄下的 Web.config 加入 <authentication mode="Forms"></authentication> 即可:

 

2. 使用「MVC」專案範本開始,外加 Web API 核心參考 (如下圖示)

在 MVC 專案範本下,預設會停用所有表單驗證功能,如果要啟用表單驗證的話,則要修改 Web.config 兩個地方:

  1. 調整 <authentication>mode 屬性為 Forms ( 原本預設值為 None )
  2. 刪除 <remove name="FormsAuthentication" /> 設定 (原本這行會停用所有表單驗證的功能)

由於 ASP.NET MVC 專案預設移除了 FormsAuthentication 模組,如果你沒有意識到這個模組預設被移除的話,會導致你的 Code 怎樣寫都能執行,登入也能跑,也不會發生例外,但登入者會永遠是「尚未登入」的鬼打牆狀態!

 

3. 使用「Web API」專案範本開始,外加 Web API 核心參考 (如下圖示)

在 Web API 專案範本下,預設也會停用所有表單驗證功能,但要改的地方又比 MVC 專案多一些,地雷實在很多啊!

如果要啟用表單驗證的話,除了要修改 Web.config 兩個地方 (跟 MVC 專案範本一樣),還要修改 App_Start\WebApiConfig.cs 檔案:

修改 Web.config 兩個地方:

  1. 調整 <authentication>mode 屬性為 Forms ( 原本預設值為 None )
  2. 刪除 <remove name="FormsAuthentication" /> 設定 (原本這行會停用所有表單驗證的功能)

image

修改 App_Start\WebApiConfig.cs 兩行程式碼,將其註解起來:

  • // config.SuppressDefaultHostAuthentication();
  • // config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

預設的 ASP.NET Web API 2 專案範本中,由於被設定成僅使用 bearer 權杖驗證,因此這兩行必須註解起來,表單驗證才能正常執行。

不過有一點要注意,如果你將這兩行註解起來的話,ASP.NET Web API 就不能走專案範本預設的 OAuth 驗證,專案內的 AccountController 也將無法正常使用!

 

本文所有程式碼,包含所有修改程式碼的版本紀錄,都已經整理到 https://github.com/doggy8088/WebApi2FormsAuth 這個專案中,大家可以先 git clone 回來,再透過 Git 工具 (TortoiseGit, SourceTree, … ) 即可查看每一個版本的變化歷程。

 

相關連結