1. 基于REACT和.NET CORE集成WINDOWS身份驗證

        共 7509字,需瀏覽 16分鐘

         ·

        2020-09-26 05:31

        有很多方法可以向您的應用程序添加身份驗證。雖然OAuth是最常見的一種,但這并不是您唯一的選擇。今天,我將向您展示如何通過React和.NET Core簡單地完成Windows身份驗證。


        探索我們的選擇

        在深入探討之前,讓我們簡要討論一些可用的其他選項。了解您的選擇,可以使您根據(jù)自己的情況做出最佳(受過良好教育)的決定。這絕不是關于替代方案的詳盡討論,而只是其中一些較流行的替代方案。

        Okta是一家身份和訪問管理公司,提供基于云的解決方案。他們有Active Directory插件/提供程序。他們的站點包含一個教程,如何開始向您的React應用程序添加身份驗證。在商業(yè)解決方案方面,該解決方案經(jīng)常被推薦使用。

        Auth0是另一個具有良好關注度的商業(yè)解決方案。他們有專門針對將Active Directory / LDAP與React結(jié)合使用的教程。

        IdentityServer是開源替代方案。就像其他人一樣,他們提供了有關如何實施Windows身份驗證的說明。他們有一個有關如何實現(xiàn)javascript客戶端(例如React)的示例。這是有關在Identity Server 4中使用SPA(反應/角度)UI的文章。

        當然,我們今天在這里討論的選擇是推出您自己的解決方案。

        為什么不選擇交鑰匙解決方案?

        盡管您的原因可能有所不同,但我想出了一些原因。

        1. 基礎結(jié)構(gòu)/資源不足,無法設置服務(適用于Identity Server 4)。

        2. 資金/預算不足,無法支付SAAS提供商的費用。

        3. 您位于防火墻之內(nèi),并且React和.NET應用程序都位于同一網(wǎng)絡上。

        4. 您喜歡挑戰(zhàn)和/或喜歡重新發(fā)明輪子(哈?。?/span>

        好的,也許最后一個有點有趣。一般來說,使用交鑰匙解決方案最好的選擇,但不是您的選擇。在我遇到的這個特殊用例中,這不是我想要的。然而。

        入門

        為了構(gòu)建此應用程序,我們需要兩件事:

        1. .NET Core API項目–該項目將處理身份驗證,授權以及API調(diào)用

        2. React應用程序–該項目是我們的GUI

        我為該項目學習和應用的東西是Google-fu精通和反復試驗編碼的結(jié)合。希望匯總我的經(jīng)驗將使您(我的讀者)比我更容易。

        我首先創(chuàng)建一個文件夾來包含我的API和React項目,然后運行dotnet new api -o ReactWindowsAuth以搭建一個新的API項目。(這實際上是一個謊言,我使用VS來創(chuàng)建應用程序,但是我們假裝使用了CLI)。從那里開始,我運行npm create-react-app test-app了一個名為的基本React應用程序test-app。就個人而言,我喜歡將Visual Studio用于.NET代碼,將VSCode用于幾乎所有其他內(nèi)容,因此我在VS中打開了新的API項目并生成了解決方案文件。

        從這里開始,我們現(xiàn)在可以開始使用React和.NET Core實施Windows身份驗證了!

        框架.NET Core API

        我們需要做的第一件事就是確保我們的應用程序以Windows身份驗證運行。由于我使用VS生成了項目并提供了Docker支持,因此我不得不做一些您可能不需要做的事情。

        啟用Windows身份驗證

        我要做的第一件事是將調(diào)試啟動器從Docker切換到IIS Express。


        切換默認啟動

        接下來,我需要打開我的launchSettings.json"windowsAuthentication": trueiisSettings下進行設置。

        啟用Windows身份驗證

        好吧,讓我們稍等一秒鐘。為了使Windows身份驗證起作用,您將需要在IIS或IIS Express中進行托管。您也可以使用KestrelHTTP.sys托管來完成此操作,但出于本文的方便,讓我們集中討論IIS Express。如果您想使它在Docker和/或Linux上運行,您將要使用Kestrel。

        我們的應用程序現(xiàn)在可以與Windows身份驗證一起使用了,但是如果我們現(xiàn)在啟動它,它仍然不會使用。我們還有很多工作要做。

        配置Windows身份驗證

        現(xiàn)在我們已經(jīng)設置了API以通過IIS使用Windows身份驗證,我們需要使API本身意識到這一點。為此,我們需要對進行一些調(diào)整Startup.cs。MSDN上有文檔,但我們也可以在這里進行閱讀。

        您需要做的第一件事是services.AddAuthentication(IISDefaults.AuthenticationScheme);在您的ConfigureServices方法中添加任何位置。這利用了Microsoft.AspNetCore.Server.IISIntegration命名空間。

        添加Windows身份驗證

        接下來,您需要配置Windows身份驗證需要保護哪些控制器或動作。順便說一下,這就是為什么我們"anonymousAuthentication": true獨自留在launchSettings.json。這里的一個用例是,如果您使用的是Swagger,并且希望匿名訪問文檔并且僅保護API本身。

        在我的用例中,我假裝我希望所有API控制器都需要身份驗證。鑒于此,我創(chuàng)建了一個WebControllerBase.cs,并用[Authorize]屬性對其進行了裝飾。請注意,您可以改為用[Authorize]標記每個控制器。就是說,我的理由實際上是押韻的,在以后的第二部分中,我將進一步闡述這個想法?,F(xiàn)在,只需滾動即可。

        WebControllerBase,將[Authorize]標記為需要身份驗證

        接下來,只需讓我們現(xiàn)有的控制器和新控制器繼承自WebControllerBase而不是即可ControllerBase。

        現(xiàn)在,我們現(xiàn)有的控制器繼承自WebControllerBase

        在網(wǎng)絡上的其他示例中,您可能會看到人們說您需要添加app.UseAuthentication()Configure(IApplicationBuilder app, IWebHostEnvironment env)方法。如果僅針對IIS / IIS Express,則不會。也就是說,添加它不會傷害您。我不會判斷你是否愿意。我的源代碼有它。

        測試一下!

        現(xiàn)在,我們可以對其進行測試了。在WeatherForecastController頂部打一個斷點:以調(diào)試模式獲取并運行Web應用程序。達到斷點時,添加監(jiān)視HttpContext.User并向下鉆取.Identity.Name。(可選)只需在方法頂部添加此行:var user = HttpContext.User?.Identity?.Name ?? "N/A";并查看結(jié)果。您的應用程序現(xiàn)在正在報告您當前的Windows用戶名,對嗎?

        哇,等等,您還沒有完成!

        我們已經(jīng)接近了,但是如果我們想在React中使用它,我們還有很多工作要做。CORS。別說了。什么是CORS?CORS是跨域資源共享,這是您要允許[this]訪問[that]的一種非常真實的方式。在現(xiàn)實世界中,默認情況下將瀏覽器配置為禁止通過腳本發(fā)起的HTTP請求,除非接收端明確允許。

        所以……讓我們做一下,這樣這個API可以接受來自React應用程序的CORS請求,對吧?我們不會在這里變得很花哨。為了使此操作生效,我們需要在中添加一些設置,appsettings.json然后在中進行其他設置Startup.cs。

        appsettings.json

        首先,我們?nèi)?/span>appsettings.json添加以下內(nèi)容:"CorsOrigins": [ "http://localhost:3000" ],。是的,它是數(shù)組類型。為什么?主要是因為它為您提供了選擇。假設在開發(fā)中,我打開了通往機器的通道,以便某人(甚至我)可以從另一臺設備訪問該應用程序。顯然,它們不會通過本地主機名或IP地址連接到localhost。所有這些都是我可能要設置的選項。

        啟動文件

        接下來,我們需要將CORS添加到我們的服務和中間件中。在ConfigureServices中,請?zhí)砑右韵麓a:

        // add this class somewhere outside of the Startup class
        public class Constants
        {
        public const string CORS_ORIGINS = "CorsOrigins";
        }

        services.AddCors(opt =>
        {
        opt.AddPolicy("CorsPolicy", builder => builder
        .AllowAnyHeader()
        .AllowAnyMethod()
        .WithOrigins(Configuration.GetSection(Constants.CORS_ORIGINS).Get())
        .AllowCredentials());
        });

        此代碼的簡要說明。它允許傳遞任何標頭,使用任何http方法(GET,POST,PUT,DELETE等),必須來自配置中特定的來源之一,并允許在標頭中傳遞憑據(jù)。在您自己的應用程序中,您可以更改許多設置。您可能不會更改其中任何一個。至少您現(xiàn)在知道它們了。

        接下來,我們需要添加app.UseCors("CorsPolicy")到我們的Configure(app, env)方法中。請注意,這是中間件和中間件順序。在這種情況下,它需要跟從app.UseRouting()但在此之前app.UseAuthentication()app.UseAuthorization()。順便說一句,如果您添加了中間件,但中間件工作不正常,則應檢查其注冊順序。


        現(xiàn)在使用app.UseCors(“ CorsPolicy”)配置方法

        現(xiàn)在我們準備好讓我們的React應用程序與Windows身份驗證掛鉤了!

        帶有React的Windows身份驗證–連接起來!

        對此感到興奮嗎?我知道我是。這比您想象的要容易。準備好了嗎?

        您需要做的就是在fetch請求中添加兩個屬性:credentials: "include"mode: 'cors'

        將會發(fā)生的情況是,如果您訪問的站點與您不在同一域(或計算機)上,則瀏覽器將提示您輸入該Active Directory,LDAP或計算機實例的憑據(jù)。成功進行身份驗證后,瀏覽器將其存儲以備將來使用。如果您在完全相同的計算機或域上,則不會提示憑據(jù)。

        話雖如此,您可以(并且可能應該)設置服務f調(diào)用的方式,因此不必在各處都輸入相同的垃圾。當我第一次開始使用React時,我很快意識到,設置一些獲取幫助程序來啟動它比較容易。我意識到的第二件事是,在React代碼中將所有.NET API控制器與“服務”進行匹配更加容易。

        考慮到這一點,讓我們看一下我的提取幫助器和示例服務。

        fetch-helpers.js

        這是我在此測試應用程序中擁有的一些基礎知識:

        export const handleResponse = (response) => {
        return response.text().then((text) => {
        ? const data = text && JSON.parse(text);
        ? if (!response.ok) {
        ? ? const error = (data && data) || response.statusText;
        ? ? return Promise.reject(error);
        ? }

        ? return data;
        });
        };

        export const requestBase = (() => {
        if (typeof window !== "undefined") {
        ? return {
        ? ? method: "POST",
        ? ? credentials: "include",
        ? ? mode: 'cors',
        ? ? headers: new Headers({
        ? ? ? Accept: "application/json",
        ? ? ? "Content-Type": "application/json",
        ? ? }),
        ? };
        } else
        ? return {
        ? ? method: "POST",
        ? ? credentials: "include",
        ? ? // mode: 'cors',
        ? ? headers: {
        ? ? ? Accept: "application/json",
        ? ? ? "Content-Type": "application/json",
        ? ? },
        ? };
        })();

        值得注意的是,requestBase如果它不是NodeJS(經(jīng)過渲染的React),則可以具有不同的返回對象。很難發(fā)現(xiàn)差異,但是無瀏覽器版本將標頭設置為Headers對象的實例,而瀏覽器版本僅設置JSON對象。

        weather-api.js

        接下來,讓我們看看我們的服務如何使用fetch-helpers。首先,下面的apiBase是完整的URL。顯然,您不會這樣做,但實際上會將React的baseUrl設置為更高的級別(通常在HTML級別)。這是示例代碼,請加一點鹽。

        import { handleResponse, requestBase } from "../_helpers";

        const apiBase = "https://localhost:44387/weatherforecast";

        class WeatherForecastService {
        getForecasts() {
        ? let request = Object.assign({}, requestBase, { method: "GET" });
        ? let url = `${apiBase}`;

        ? return fetch(url, request).then(handleResponse);
        }

        getProtectedForecast() {
        ? let request = Object.assign({}, requestBase, { method: "GET" });
        ? let url = `${apiBase}/5`;

        ? return fetch(url, request).then(handleResponse);
        }
        }

        const instance = Object.freeze(new WeatherForecastService());
        export { instance as WeatherForecastService };

        我在這里所做的只是公開我希望React可以訪問的方法,將它們包裝在baseRequestfrom的周圍,并fetch-helpers使用我的handleResponsefrom 來處理響應fetch-helpers,然后傳遞回調(diào)用方。

        最后但同樣重要的是,將其連接起來!

        現(xiàn)在我們已經(jīng)鋪設了所有管道,現(xiàn)在該連接所有東西了。我只是直接編輯App.js。告我。對于該示例,我將導入所有三個API服務文件,然后const為我要處理的每個按鈕設置一些功能。其中的每一個都僅注銷到控制臺,而不用花費大量精力。最后,當然是按鈕本身。由于該文件在修改后相當龐大,因此我僅摘錄了按鈕事件之一以及調(diào)用它的React按鈕組件本身。

        const getProtectedForecast = () => {
        console.log("attempting...");

        WeatherForecastService.getProtectedForecast()
        .then((response) => {
        console.log("response: ", JSON.stringify(response));
        console.log("oh boy!");
        })
        .catch((err) => {
        console.error(err);
        });
        };

        重要環(huán)節(jié)– Windows身份驗證基于角色的安全性

        雖然上述設置是非?;镜?,但它缺少一個非常重要的部分,不是嗎?基于角色的安全性。在這里考慮一下此內(nèi)容,這是對第2部分的非常簡短的介紹,而我將在不久的將來寫一篇文章。如果你已經(jīng)點擊周圍的代碼,而閱讀這篇文章,你可能已經(jīng)注意到在Startup.cs以下行:ConfigureServices:services.AddTransient();。如果您沒有注意到它,那是可以的,因為我現(xiàn)在將談論它。

        在對用戶進行身份驗證之后但在獲得授權之前,授權提供者將調(diào)用您的自定義IClaimsTransformation實現(xiàn)(如果提供)。參見MSDN。在我的實現(xiàn)中(位于中ClaimsTransformer),您將看到我只是在隨意添加角色“ Super-awesome”作為我們WindowsIdentity用于其聲明類型的相同聲明類型。

        IClaimsTransformation的ClaimsTransformer實現(xiàn)者

        接下來,您可能已經(jīng)注意到WeatherForecastController我添加了一個GetAnother方法調(diào)用,該方法調(diào)用需要“超級棒”角色。在此之下,我還添加了一種GetFail方法,該方法將始終失敗,因為用戶不在“管理員”角色中。這些方法都沒有連接到React應用程序中,并且要求您直接在瀏覽器中單擊它們以查看它們是否有效(或可能無效)。

        基于Controller動作的基于角色的Windows身份驗證

        結(jié)論

        將Windows身份驗證連接到您的React應用程序并不困難。這也是非常基本的。交鑰匙解決方案可以使您走得更快,更遠,但是如果您沒有基礎設施或現(xiàn)金,仍然可以自己動手做。和往常一樣,我博客文章中的代碼可以在GitHub找到。


        瀏覽 50
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 特级操逼 | 潘金莲做爰床戏呻吟 | 另类三区 | 欧美少妇bb| 熟妇一区二区 |