Web API表單驗證

by vivid 7. 二月 2018 16:49

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N180219201
出刊日期: 2018/2/7

目前遇到一個需求,需要在ASP.NET Web Forms網站(Web Site)之中設計一個Web API,將採用表單式驗證(FormsAuthentication)來驗證用戶端程式,然後在另一個Web Form網站使用「HttpClient」類別來呼叫這個Web API。

因為預設Visual Studio 沒有網站類型的Web API範本專案,因此需要將Web API的路由與相關套件手動加入,本文將介紹如何在ASP.NET Web Forms網站(Web Site)安裝Web API所需的套件,並手動設定Web API路由,最後達到使用「HttpClient」類別進行表單驗證,並叫用Web API取回執行結果。本文所提及的技術適用於ASP.NET Web Form與.NET Framework 4.6以上版本。

 

設計Web API網站

首先讓我們從設計Web API網站開始。從 Visual Studio 2017的主選單點選「File」-「New」-「Web Site」項目,開啟「New Web Site」對話窗,請參考下圖所示:

clip_image002

圖 1:開啟「New Web Site」對話窗。

若Visual Studio 2017更新到15.5.1版或以上版本,則「New」-「Web Site」選單的位置搬家了,需要從 Visual Studio 2017的主選單點選「File」-「New」-「Project」,接著會開啟「New Project」對話窗。選取「Visual C#」-「Web」-「Web Site」項目,請參考下圖所示:

clip_image004

圖 2:開啟「New Project」對話窗。

在「New Web Site」對話窗確認視窗上方.NET Framework的目標版本為「.NET Framework 4.6.1以上」,選取使用的程式語言 (Language)為「Visual C#」,然後選取「ASP.NET Empty Web Site」,將「Web Location」設為「File System」,選取檔案存放資料夾設定名稱為「WebAPIWebSite」,請參考下圖所示:

clip_image006

圖 3:建立「ASP.NET Empty Web Site」。

安裝「Microsoft.AspNet.WebApi.WebHost」套件

使用Nuget套件管理員下載「Microsoft.AspNet.WebApi.WebHost」套件。自Visual Studio 2017開發工具選單選取「Website」-「Manage NuGet Packages」項目,開啟「「NuGet Packages Manage」。在「Browse」分頁上方文字方塊輸入「webapi」當作篩選條件,找出套件之後,只要點選名稱旁邊的「Install」按鈕安裝,請參考下圖所示:

clip_image008

圖 4:安裝「Microsoft.AspNet.WebApi.WebHost」套件。

安裝「Microsoft.AspNet.WebApi.WebHost」套件會順便幫你安裝「Microsoft.AspNet.WebApi.Client」、「Microsoft.AspNet.WebApi.Core」與「Newtonsoft.Json」套件,請參考下圖所示:

clip_image010

圖 5:安裝WebApi 相關套件。

從「Solution Explorer」視窗 -「WebAPIWebSite」資料夾上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Add New Item」項目,請參考下圖所示:

clip_image012

圖 6:「Add New Item」。

從「Add New Item」對話盒中,選取「Visual C#」-「Class」項目,然後在下方將「Name」設定為「WebApiConfig.cs」最後按下「Add」按鈕,請參考下圖所示:

clip_image014

圖 7:加入「WebApiConfig.cs」類別。

此時Visual Studio開發工具會提示是否將此類別放在「App_Code」資料夾,在此按下「Yes」按鈕,請參考下圖所示:

clip_image016

圖 8:建立「App_Code」資料夾。

在「WebApiConfig.cs」檔案中加入程式碼,設定Web API路由,參考以下範例程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;

public static class WebApiConfig {
  public static void Register( HttpConfiguration config ) {
    config.MapHttpAttributeRoutes( );

    config.Routes.MapHttpRoute(
        name: "DefaultApi" ,
        routeTemplate: "api/{controller}/{id}" ,
        defaults: new { id = RouteParameter.Optional }
    );
  }
}

 

從「Solution Explorer」視窗 「WebAPIWebSite」網站資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「Add New Item」選項,選取「Visual C#」分類中的「Global Application Class」項目,檔案名稱設定為「Global.asax」,然後按下「Add」按鈕,請參考下圖所示:

clip_image018

圖 9:加入「Global Application Class」檔案。

在「Global.asax」檔案最上方引用「System.Web.Http」命名空間,並在「Application_Start」事件處理常式中加入程式碼,註冊Web API路由:

<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Http" %>
<script RunAt="server">

  void Application_Start( object sender , EventArgs e ) {
      GlobalConfiguration.Configure( WebApiConfig.Register );
  }

  void Application_End( object sender , EventArgs e ) {
  }

  void Application_Error( object sender , EventArgs e ) {
  }

  void Session_Start( object sender , EventArgs e ) {
  }

  void Session_End( object sender , EventArgs e ) {
  }

</script>

 

在「App_Code」資料夾加入Web API。從「Solution Explorer」視窗 -「WebAPIWebSite」-「App_Code」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「Add New Item」項目,開啟「Add New Item」對話盒,選取「Visual C#」分類下的「Web API Controller Class (v2.1)」,然後按下「Add」按鈕,請參考下圖所示:

clip_image020

圖 10:加入「Web API Controller Class (v2.1)」。

在「MyAPIController」類別階層宣告一個「employees」集合,並新增多筆員工資料,然後在「Get」方法中回傳「employees」物件所成的集合,參考以下範例程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

public class MyAPIController : ApiController {
  static List<string> employees =
    new List<string> { "Mary" , "Candy" , "Lilly" , "Betty" , "Jessica" };
  public IEnumerable<string> Get( ) {
    return employees;
  }
}

 

選取Visual Studio 開發工具「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:65235/api/myapi

執行結果參考如下,以下是使用Chrome瀏覽器呼叫時,回傳的XML資料:

clip_image022

圖  11:呼叫Web API測試。

設計「Generic Handler」進行驗證

我們需要在伺服端提供表單驗證,這次我選擇使用「Generic Handler 」來進行驗證。從「Solution Explorer」視窗 -「WAPIWebsite」資料夾上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Add New Item」項目,從「Add New Item」對話盒中,選取「Visual C#」分類下的「Generic Handler」項目,然後在下方將「Name」設定為「MyHandler」最後按下「Add」按鈕,請參考下圖所示:

clip_image024

圖 12:加入「Generic Handler」。

參考以下範例程式碼,修改「MyHandler」類別的「ProcessRequest」方法,先取得用戶端傳入的帳號(username)與密碼(password),本例假設帳號為「AAA」密碼為「111」時代表驗證成功,驗證成功後利用「FormsAuthentication」類別的「SetAuthCookie」方法設定驗證Cookie,然後設定HTTP狀態碼為「200」;若帳號、密碼不相符則送出狀態碼「401」代表驗證不通過。

<%@ WebHandler Language="C#" Class="MyHandler" %>

using System;
using System.Web;
using System.Web.Security;

public class MyHandler : IHttpHandler {

    public void ProcessRequest( HttpContext context ) {
        var username = context.Request.Params ["username"];
        var password = context.Request.Params ["password"];
        if ( username == "AAA" && password == "111" ) {
            FormsAuthentication.SetAuthCookie( username , true );
            context.Response.StatusCode = 200;
            context.Response.StatusDescription = "OK";

        } else {
            context.Response.StatusCode = 401;
            context.Response.StatusDescription = "Unauthorized";
        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

 

使用Web.config組態檔啟用表單驗證

最後透過Web.config組態檔啟用表單驗證,在Web.config檔案中加入< authentication>與< authorization >標籤。< authentication>的「mode」設定為「Forms」表示使用表單驗證,「loginUrl」則用來設定驗證的程式為「MyHandler.ashx」。< authorization >標籤中使用<deny>項目設定拒絕匿名者存取(?號代表匿名者),參考以下範例程式碼:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/MyHandler.ashx" />
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
    <compilation debug="true" targetFramework="4.6.1">
      <assemblies>
        <add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
      </assemblies>
    </compilation>
    <httpRuntime targetFramework="4.6.1" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
</configuration>

 

選取Visual Studio 開發工具「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行網站首頁(請注意:埠號可能會依據實際上的操作而有所不同,請修改為實際的埠號),然後在瀏覽器輸入以下URL:

http://localhost:65235/api/myapi

這次的執行結果參考如下,以下是使用Chrome瀏覽器呼叫時回傳的結果,因為沒有提供驗證所需的帳號與密碼來驗證,你將得到一個「401」號錯誤:

clip_image026

圖 13:驗證發生錯誤。

設計ASP.NET Web Form網站

接下來我們要設計ASP.NET Web Form網站當做Web API的用戶端程式。先在「Visual Studio 2017」目前方案中,加入一個新的網站。從「Solution Explorer」視窗點選「Solution ...」項目,按滑鼠右鍵,從快捷選單選擇「Add」- 「New Web Site」項目,開啟「Add New Web Site」對話窗,請參考下圖所示:

clip_image028

圖 14:「Add New Web Site」。

確認「Add New Web Site」視窗上方.NET Framework的目標版本為「.NET Framework 4.6.1以上」,選取使用的程式語言 (Language)-「 Visual C#」,然後選取「ASP.NET Empty Web Site」,將「Web Location」設為「File System」,並設定資料夾名稱為「WebFormWebSite」,請參考下圖所示:

clip_image030

圖 15:加入Web Form用戶端。

安裝「Microsoft.AspNet.WebApi.Client」套件

在ASP.NET Web Form網站,使用Nuget套件管理員下載「Microsoft.AspNet.WebApi.Client」套件。自Visual Studio開發工具選單選取「Website」-「Manage NuGet Packages」項目,開啟「「NuGet Packages Manage」。在「Browse」分頁上方文字方塊輸入「webapi」當作篩選條件,找出套件之後,只要點選名稱旁邊的「Install」按鈕安裝,請參考下圖所示:

clip_image032

圖 16:安裝「Microsoft.AspNet.WebApi.Client」套件。

安裝「Microsoft.AspNet.WebApi.WebHost」套件會順便幫你安裝「Newtonsoft.Json」套件,請參考下圖所示:

clip_image034

圖 17:安裝「Newtonsoft.Json」套件。

選取「I Accept」接受授權,請參考下圖所示:

clip_image036

圖 18:接受授權。

加入「System.Net.Http」組件參考

ASP.NET Web Form網站加入「System.Net.Http」組件參考。從「Soluiton Explorer」視窗,「WebFormWebSite」網站名稱上按滑鼠右鍵,從快捷選單選擇「Add」-「Reference」項目,開啟「Reference Manager」視窗,選取「Assemblies」分類,勾選「System.Net.Http」組件,然後按下「OK」按鈕,請參考下圖所示:

clip_image038

圖 19:加入「System.Net.Http」組件參考。

在「Solution Explorer」視窗,點選「WebFormWebSite」網站,按滑鼠右鍵,從快捷選單選擇「Add」-「Add New Item...」。從「Add New Item」對話盒中,選取「Visual C#」-「Web Form」項目,然後在下方將「Name」設定為「Default.aspx」,勾選「Place code in separate file」核取方塊,最後按下「Add」按鈕建立網頁,請參考下圖所示:

clip_image040

圖 20:加入「Default.aspx」。

 

修改Default.aspx網頁,從「Toolbox」拖曳一個「GridView」與「Label」控制項到表單<form>標籤之中,然後將「Label」控制項的「ID」設為「msg」;將「Text」屬性設為空字串,目前「Default.aspx」檔案程式碼看起來如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="GridView1" runat="server">
            </asp:GridView>
        </div>
        <asp:Label ID="msg" runat="server" Text=""></asp:Label>
    </form>
</body>
</html>


 

修改「Default.aspx.cs」檔案,在Page_Load事件處理常式中加入以下程式碼,範例中利用「HttpClient」類別的「SendAsync」方法,送出兩個請求,第一個請求將帳號與密碼送到Web API進行驗證,以取得驗證Cookie,第二個請求則是叫用Web API取回員工清單,參考以下範例程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page {
  protected void Page_Load( object sender , EventArgs e ) {
    var username = "AAA";
    var password = "111";

    var client = new HttpClient( );
    var authRequest = new HttpRequestMessage( ) {
      RequestUri = new Uri( "http://localhost:65235/MyHandler.ashx" ) ,
      Method = HttpMethod.Post ,
      Content = new FormUrlEncodedContent(
            new List<KeyValuePair<string , string>> {
                    new KeyValuePair<string, string>("Username", username),
                    new KeyValuePair<string, string>("Password", password)
    } )
    };

    var authResponse = client.SendAsync( authRequest ).Result;
    if ( authResponse.IsSuccessStatusCode ) {
      var authCookies = FormsAuthentication.GetAuthCookie( username , false );

      var request = new HttpRequestMessage( ) {
        RequestUri = new Uri( "http://localhost:65235/api/myapi" )
      };

      Response.AppendCookie( authCookies );
      var response = client.SendAsync( request ).Result;
      var r = response.Content.ReadAsAsync<IEnumerable<string>>( ).Result;

      GridView1.DataSource = r;
      GridView1.DataBind( );
    } else {
      msg.Text = "發生錯誤! ";
      msg.Text += "<br/> ";
      msg.Text += "錯誤狀態碼 : " + authResponse.StatusCode;
    }
  }
}

 

測試

使用Visual Studio開發工具進行測試,選取「Solution Explorer」視窗中的「Solution…」項目,按滑鼠右鍵,從快捷選單選擇「Properties」項目,請參考下圖所示:

clip_image042

圖 21:設定專案屬性。

在「Property Pages」對話盒中,選取「Common Properties」-「Startup Project」分頁。設定「Multiple startup projects」,將「WebAPIWebSite」與「WEbFormWebSite」的「Action」設為「Start」,記得順序需要先「WebAPIWebSite」網站再「WEbFormWebSite」網站,若順序有錯可以使用右方的箭頭按鈕進行調整,請參考下圖所示:

clip_image044

圖 22:設定起始專案。

選取Visual Studio 開發工具「Build」-「Build Solution」編譯目前的專案,確認程式碼能正確編譯。按CTRL+F5執行,此時應該可以看到「WebFormWebSite」網站的ASP.NET Web Form(Default.aspx)可以叫用到Web API,並取回員工清單顯示在「GridView」控制項上,請參考下圖所示:

clip_image046

圖 23:呼叫Web API結果。

若帳號、密碼不相符將會看到以下錯誤訊息:

clip_image048

圖 24:呼叫Web API失敗。

最後再提醒,若選擇使用此種方式做驗證,建議再搭配SSL 才能確保帳號與密碼的安全。

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET | ASP.NET Web API | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List