IdentityServer4 快速入門#6:添加JavaScript客戶端

注意
對于任何先決條件(例如模板),請先查看概述。

本快速入門將展示如何構建基于瀏覽器的JavaScript客戶端應用程序(有時稱為“單頁應用程序”或“ SPA”)。

用戶將登錄到IdentityServer,使用由IdentityServer發行的訪問令牌調用Web API,然后注銷IdentityServer。 所有這些將由瀏覽器中運行的JavaScript驅動。

JavaScript客戶端的新項目

為JavaScript應用程序創建一個新項目。 它可以只是一個空的Web項目,一個空的ASP.NET Core應用程序或其他類似Node.js的應用程序。 本快速入門將使用ASP.NET Core應用程序。

在?/ src目錄中創建一個新的“空” ASP.NET Core Web應用程序。 您可以使用Visual Studio或從命令行執行此操作:

md JavaScriptClient
cd JavaScriptClient
dotnet new web

修改主機

修改JavaScriptClient項目以在端口5003上運行。

添加靜態文件中間件

鑒于此項目旨在運行在客戶端,因此我們需要ASP.NET Core要做的就是提供將構成我們的應用程序的靜態HTML和JavaScript文件。 靜態文件中間件就是為此目的而設計的。

Configure方法中的Startup.cs中注冊靜態文件中間件(并同時刪除其他所有內容):

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

現在,該中間件將提供應用程序?/ wwwroot文件夾中的靜態文件。 我們將在此處放置HTML和JavaScript文件。 如果您的項目中不存在該文件夾,請立即創建它。

參考oidc-client

在基于ASP.NET Core MVC的客戶端項目中的先前快速入門中,我們使用一個庫來處理OpenID Connect協議。 在JavaScriptClient項目的這一快速入門中,我們需要一個類似的庫,只是該庫可在JavaScript中運行并被設計為在瀏覽器中運行。 oidc-client library就是這樣一種庫。 它可以通過NPMBower
和從github直接下載獲得。

NPM

如果要使用NPM下載oidc-client,請從JavaScriptClient項目目錄運行以下命令:

npm i oidc-client
copy node_modules\oidc-client\dist\* wwwroot

這將在本地下載最新的oidc-client軟件包,然后將相關的JavaScript文件復制到~/wwwroot中,以便您的應用程序可以使用它們。

說明書下載

如果您只想簡單地手動下載oidc-client JavaScript文件,請瀏覽到GitHub存儲庫并下載JavaScript文件。 下載后,將它們復制到~/wwwroot,以便您的應用程序可以使用它們。

添加您的HTML和JavaScript文件

接下來是將HTML和JavaScript文件添加到~/wwwroot。 除了oidc-client.js庫,我們將有兩個HTML文件和一個特定于應用程序的JavaScript文件。 在~/wwwroot中,添加一個名為index.html和callback.html的HTML文件,并添加一個名為app.js的JavaScript文件。

index.html

這將是我們應用程序中的主頁。 它僅包含用于用戶登錄,注銷和調用Web API的按鈕的HTML。 它還將包含<script>標記,以包含我們的兩個JavaScript文件。 它還將包含用于向用戶顯示消息的<pre>。

它看起來應該像這樣:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <button id="login">Login</button>
    <button id="api">Call API</button>
    <button id="logout">Logout</button>

    <pre id="results"></pre>

    <script src="oidc-client.js"></script>
    <script src="app.js"></script>
</body>
</html>
app.js

這將包含我們應用程序的主要代碼。 第一件事是添加一個輔助函數以將消息記錄到<pre>:

function log() {
    document.getElementById('results').innerText = '';

    Array.prototype.forEach.call(arguments, function (msg) {
        if (msg instanceof Error) {
            msg = "Error: " + msg.message;
        }
        else if (typeof msg !== 'string') {
            msg = JSON.stringify(msg, null, 2);
        }
        document.getElementById('results').innerHTML += msg + '\r\n';
    });
}

接下來,添加代碼以將click事件處理程序注冊到三個按鈕:

ocument.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);

接下來,我們可以使用oidc-client庫中的UserManager類來管理OpenID Connect協議。 它需要MVC客戶端中必需的類似配置(盡管具有不同的值)。 添加以下代碼以配置和實例化UserManager

var config = {
    authority: "http://localhost:5000",
    client_id: "js",
    redirect_uri: "http://localhost:5003/callback.html",
    response_type: "code",
    scope:"openid profile api1",
    post_logout_redirect_uri : "http://localhost:5003/index.html",
};
var mgr = new Oidc.UserManager(config);

接下來,UserManager提供一個getUser API,以了解用戶是否已登錄到JavaScript應用程序。 它使用JavaScript Promise異步返回結果。 返回的User對象具有一個profile文件屬性,其中包含該用戶的聲明。 添加以下代碼以檢測用戶是否登錄到JavaScript應用程序:

mgr.getUser().then(function (user) {
    if (user) {
        log("User logged in", user.profile);
    }
    else {
        log("User not logged in");
    }
});

接下來,我們要實現loginapilogout函數。UserManager提供用于登錄用戶的signinRedirect和用于注銷用戶的signoutRedirect。 我們在上面的代碼中獲得的User對象還具有access_token屬性,可用于對Web API進行身份驗證。 access_token將通過帶有承載方案的Authorization標頭傳遞到Web API。 添加以下代碼以在我們的應用程序中實現這三個功能:

function login() {
    mgr.signinRedirect();
}

function api() {
    mgr.getUser().then(function (user) {
        var url = "http://localhost:5001/identity";

        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = function () {
            log(xhr.status, JSON.parse(xhr.responseText));
        }
        xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
        xhr.send();
    });
}

function logout() {
    mgr.signoutRedirect();
}
Note

請參閱客戶端憑據快速入門 有關如何創建以上代碼中使用的api的信息。

callback.html

用戶登錄到IdentityServer后,此HTML文件就是指定的redirect_uri頁面。 它將完成與IdentityServer的OpenID Connect協議登錄握手。 這些代碼全部由我們之前使用的UserManager類提供。 登錄完成后,我們可以將用戶重定向回index.html主頁。 添加以下代碼以完成登錄過程:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <script src="oidc-client.js"></script>
    <script>
        new Oidc.UserManager({response_mode:"query"}).signinRedirectCallback().then(function() {
            window.location = "index.html";
        }).catch(function(e) {
            console.error(e);
        });
    </script>
</body>
</html>

將客戶端注冊添加到IdentityServer的JavaScript客戶端

現在客戶端應用程序已準備就緒,我們需要在IdentityServer中為此新的JavaScript客戶端定義配置條目。 在IdentityServer項目中,找到客戶端配置(在Config.cs中)。 將新客戶端添加到我們的新JavaScript應用程序的列表中。 它應該具有下面列出的配置:

// JavaScript Client
new Client
{
    ClientId = "js",
    ClientName = "JavaScript Client",
    AllowedGrantTypes = GrantTypes.Code,
    RequirePkce = true,
    RequireClientSecret = false,

    RedirectUris =           { "http://localhost:5003/callback.html" },
    PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
    AllowedCorsOrigins =     { "http://localhost:5003" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "api1"
    }
}

允許使用CORS對Web API進行Ajax調用

最后需要進行的配置是在Web API項目中配置CORS。 這將允許從http://localhost:5003http://localhost:5001進行Ajax調用。

配置CORS

在Startup.cs的ConfigureServices中將CORS服務添加到依賴項注入系統:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;

            options.ApiName = "api1";
        });

    services.AddCors(options =>
    {
        // this defines a CORS policy called "default"
        options.AddPolicy("default", policy =>
        {
            policy.WithOrigins("http://localhost:5003")
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
    });
}

在配置中將CORS中間件添加到Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseCors("default");

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

運行JavaScript應用程序

現在您應該能夠運行JavaScript客戶端應用程序:

image.png

單擊“Login”按鈕以登錄用戶。將用戶返回到JavaScript應用程序后,您應該看到其個人資料信息:

image.png

然后單擊“ API”按鈕以調用Web API:

image.png

最后單擊“Logout”以注銷用戶。

image.png

現在,您將啟動一個JavaScript客戶端應用程序,該應用程序使用IdentityServer進行登錄,注銷和驗證對Web API的調用。

Source code here

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容