IdentityServer4_4.添加JavaScript客户端
4.添加 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
正如我们之前所做的那样,对于其他客户项目,也将此项目添加到您的解决方案中。从包含 sln 文件的根文件夹运行:
dotnet sln add .\src\JavaScriptClient\JavaScriptClient.csproj
修改托管
修改JavaScriptClient项目以在https://localhost:5003 上运行。
添加静态文件中间件
鉴于此项目旨在运行客户端,我们需要 ASP.NET Core 做的就是提供构成我们应用程序的静态 HTML 和 JavaScript 文件。静态文件中间件就是为此而设计的。
注册在静态文件中间件Startup.cs的Configure
方法(和在同一时间删除一切):
public void Configure(IApplicationBuilder app)
{
app.UseDefaultFiles();
app.UseStaticFiles();
}
这个中间件现在将从应用程序的~/wwwroot文件夹中提供静态文件。这是我们将放置 HTML 和 JavaScript 文件的地方。如果您的项目中不存在该文件夹,请立即创建它。
参考oidc-client
在之前基于 ASP.NET Core MVC 的客户端项目的快速入门之一中,我们使用了一个库来处理 OpenID Connect 协议。在JavaScriptClient项目的这个快速入门中,我们需要一个类似的库,除了一个在 JavaScript 中工作并设计为在浏览器中运行的库。该OIDC客户端库就是这样一个图书馆。它可以通过NPM、Bower 获得,也可以从 github直接下载。
新产品管理
如果要使用 NPM 下载oidc-client,请从JavaScriptClient项目目录运行以下命令:
npm i oidc-client
copy node_modules\oidc-client\dist\* wwwroot
添加您的 HTML 和 JavaScript 文件
接下来是将您的 HTML 和 JavaScript 文件添加到~/wwwroot。我们将有两个 HTML 文件和一个特定于应用程序的 JavaScript 文件(除了oidc-client.js库)。在~/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
事件处理程序注册到三个按钮:
document.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);
接下来,我们可以使用UserManager
类从OIDC客户端库来管理ID连接协议。它需要在 MVC 客户端中所需的类似配置(尽管具有不同的值)。添加此代码以配置和实例化UserManager
:
var config = {
authority: "https://localhost:5001",
client_id: "js",
redirect_uri: "https://localhost:5003/callback.html",
response_type: "code",
scope:"openid profile api1",
post_logout_redirect_uri : "https://localhost:5003/index.html",
};
var mgr = new Oidc.UserManager(config);
接下来,UserManager
提供一个getUser
API 来了解用户是否已登录到 JavaScript 应用程序。它使用 JavaScriptPromise
异步返回结果。返回的User
对象具有profile
包含用户声明的属性。添加此代码以检测用户是否登录到 JavaScript 应用程序:
mgr.getUser().then(function (user) {
if (user) {
log("User logged in", user.profile);
}
else {
log("User not logged in");
}
});
接下来,我们要实现的login
,api
和logout
功能。在UserManager
提供了signinRedirect
登录用户,并且signoutRedirect
以注销用户。User
我们在上面的代码中获得的对象也有一个access_token
属性,可用于对 Web API 进行身份验证。在access_token
将被传递给通过网络API授权的文件头和承载方案。添加此代码以在我们的应用程序中实现这三个功能:
function login() {
mgr.signinRedirect();
}
function api() {
mgr.getUser().then(function (user) {
var url = "https://localhost:6001/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();
}
callback.html
redirect_uri
一旦用户登录到 IdentityServer,这个 HTML 文件就是指定的页面。它将完成与 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>
为 JavaScript 客户端向 IdentityServer 添加客户端注册
现在客户端应用程序已准备就绪,我们需要在 IdentityServer 中为这个新的 JavaScript 客户端定义一个配置条目。在 IdentityServer 项目中找到客户端配置(在Config.cs 中)。将新客户端添加到我们新 JavaScript 应用程序的列表中。它应该具有下面列出的配置:
// JavaScript Client
new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
AllowedGrantTypes = GrantTypes.Code,
RequireClientSecret = false,
RedirectUris = { "https://localhost:5003/callback.html" },
PostLogoutRedirectUris = { "https://localhost:5003/index.html" },
AllowedCorsOrigins = { "https://localhost:5003" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
}
允许使用 CORS 对 Web API 进行 Ajax 调用
必需的最后一点配置是在 Web API 项目中配置 CORS。这将允许从https://localhost:5003到https://localhost:6001进行 Ajax 调用。
配置 CORS
添加到依赖注入系统CORS服务ConfigureServices
在Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins("https://localhost:5003")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
将 CORS 中间件添加到管道中Configure
(在路由之后):
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseCors("default");
// ...
}
运行 JavaScript 应用程序
现在您应该能够运行 JavaScript 客户端应用程序:
单击“登录”按钮让用户登录。一旦用户返回 JavaScript 应用程序,您应该会看到他们的个人资料信息:
然后单击“API”按钮调用 Web API: