Identity Server 4 从入门到落地(六)—— 简单的单页面客户端
前面的部分:
Identity Server 4 从入门到落地(一)—— 从IdentityServer4.Admin开始
Identity Server 4 从入门到落地(二)—— 理解授权码模式
Identity Server 4 从入门到落地(三)—— 创建Web客户端
Identity Server 4 从入门到落地(四)—— 创建Web Api
Identity Server 4 从入门到落地(五)—— 使用Ajax 访问 Web Api
认证服务和管理的github地址: https://github.com/zhenl/IDS4Admin
客户端及web api示例代码的github地址:https://github.com/zhenl/IDS4ClientDemo
前面我们在Web应用的页面上使用Ajax访问Web Api, 这种情况下,认证以及获取Access Token还是在后台进行的,而真正的单页面应用没有后台的参与,web服务器只起到host文件的作用,这部分我们编写简单的单页面应用,试验一下单页面访问受认证保护的Web Api。
我们参考Identity Server 4的官网示例编写这个单页面应用,将其中的认证服务器改为我们本地运行的认证服务http://localhost:4010,Web Api使用前面编写的简单示例,地址为http://localhost:5153。在编写之前,首先下载oidc的客户端,可以从github下载: https://github.com/IdentityModel/oidc-client-js/releases/tag/1.11.5 。我们使用编译完成的最终文件,将下载的文件解压,dist目录就是我们需要的文件。
首先使用Visual Studio 2022创建一个空的Asp.Net Core Web项目,我们使用这个项目作为html和js文件的宿主,除此之外不做其它工作。在项目目录下创建wwwroot目录,用于保存html和js文件,将下载的dist目录拷贝到这个目录中,目录名字改为oidc-client-js-1.11.5。然后在wwwroot下创建index.html、callback.html和app.js三个文件,文件的内容在后面填写。项目的结构如下:

然后修改lanuchSettings.json,项目的运行地址是http://localhost:5210:
{
"profiles": {
"IDS4ClientJS": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5210",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
接下来修改program.cs,使应用支持静态文件:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
这样修改后,项目将Index.html作为缺省页面。
然后就是修改Index.html、callback.html和app.js中的内容。
Index.html中的内容如下:
<!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-1.11.5/oidc-client.js"></script>
<script src="app.js"></script>
</body>
</html>
内容很简单,就是创建三个按钮,分别是登录、登出和调用Api。所实现的功能在app.js中定义:
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';
});
}
document.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);
var config = {
authority: "http://localhost:4010",
client_id: "js",
redirect_uri: "http://localhost:5210/callback.html",
response_type: "code",
scope: "openid profile myapi",
post_logout_redirect_uri: "http://localhost:5210/index.html",
};
var mgr = new Oidc.UserManager(config);
mgr.getUser().then(function (user) {
if (user) {
log("User logged in", user.profile);
}
else {
log("User not logged in");
}
});
function login() {
mgr.signinRedirect();
}
function api() {
mgr.getUser().then(function (user) {
var url = "http://localhost:5153/WeatherForecast";
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();
}
app.js使用oidc js客户端中定义的Oidc.UserManager实现对认证服务器的访问,完成认证和获取access token的工作,其配置在config 中定义,
var config = {
authority: "http://localhost:4010",
client_id: "js",
redirect_uri: "http://localhost:5210/callback.html",
response_type: "code",
scope: "openid profile myapi",
post_logout_redirect_uri: "http://localhost:5210/index.html",
};
最后,定义callback.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script src="oidc-client-js-1.11.5/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>
到此,客户端编写完成,我们还需要在认证服务管理中定义这个客户端,注意,在定义时需要选择单页面应用:

参考上面config中的定义设置客户端的其它部分:


最后一项工作是修改Web Api,增加这个网址的CORS设置:
builder.Services.AddCors(option => option.AddPolicy("cors",
policy => policy.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.WithOrigins(new[] { "https://localhost:7002", "http://localhost:5210" })));
好了,现在可以测试一下这个应用了,在Visual Studio中将解决方案的启动项目设置为多项目启动,同时启动JSClient和Web Api项目:

按F5运行,界面如下:

点击Login,会重定位到认证服务器的登录界面,登录完成后会显示用户的信息:

点击Call Api,会访问Web Api并显示结果:

到此,单页面客户端完成。相关代码可以从github下载: https://github.com/zhenl/IDS4ClientDemo 。
Identity Server 4 从入门到落地(六)—— 简单的单页面客户端的更多相关文章
- Identity Server 4 从入门到落地(八)—— .Net Framework 客户端
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(三)—— 创建Web客户端
书接上回,我们已经搭建好了基于Identity Server 4的认证服务和管理应用(如果还没有搭建,参看本系列前两部分,相关代码可以从github下载:https://github.com/zhen ...
- Identity Server 4 从入门到落地(七)—— 控制台客户端
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(九)—— 客户端User和Role的解析
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(十)—— 编写可配置的客户端和Web Api
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(十一)—— Docker部署
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(十二)—— 使用Nginx集成认证服务
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(五)—— 使用Ajax访问Web Api
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- Identity Server 4 从入门到落地(四)—— 创建Web Api
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
随机推荐
- android tcp通讯
Andoird TCP通讯 前言 最近在写一个即时通讯的项目,有一些心得,写出来给大家分享指正一下. 简单描述一下这个项目: 实时查询车辆运行状态的项目,走TCP通迅. 接口采用GZIP压缩. 后台是 ...
- 关于stm32串口必须要学的5个串口以及串口应用和注意事项
串口是我们常用的一个数据传输接口,STM32F103系列单片机共有5个串口. 其中1-3是通用同步/异步串行接口USART(Universal Synchronous/Asynchronous Rec ...
- linux下的IO模型---学习笔记
1.linux文件系统和缓存 文件系统接口 文件系统-一种把数据组织成文件和目录的存储方式,提供了基于文件的存取接口,并通过文件权限控制访问. 存储层次 文件系统缓存 主存(通常时DRAM)的一块区域 ...
- js计算精确度丢失问题解决
(function () { var calc = { /* 函数,加法函数,用来得到精确的加法结果 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精 ...
- Relocations in generic ELF (EM: 40)
最近在搞机器上的wifi热点,需要移植一大堆东西,如hostapd\wpa_suppliant.dhcp等,这些玩意又依赖其他的一大堆库的移植,比如libnl,openssl等,今天在移植编译libn ...
- Windows内核基础知识-5-调用门(32-Bit Call Gate)
Windows内核基础知识-5-调用门(32-Bit Call Gate) 调用门有一个关键的作用,就是用来提权.调用门其实就是一个段. 调用门: 这是段描述符的结构体,里面的s字段用来标记是代码段还 ...
- 在Delphi中高效执行JS代码
因为一些原因,需要进行encodeURIComponent和decodeURIComponent编码,在Delphi中找了一个,首先是发现不能正确编码+号,后面强制处理替换了,勉强可用. 后面发现多次 ...
- Trap (陷入/中断) 源码解析
用户空间和内核空间之间的切换通常称为trap trap的三种形式 系统调用引发 异常发生 设备中断 (时间中断.IO中断.网络中断等) supervise mode的权限 用户态和内核态之间的到底有什 ...
- robot_framewok自动化测试--(9)连接并操作 MySql 数据库
连接并操作 MySql 数据库 1.mysql数据库 1.1安装mysql数据库 请参考我的另一篇文章:MYSQL5.7下载安装图文教程 1.2.准备测试数据 请参考我的另一篇文章:Mysql基础教程 ...
- SpringBoot 中发布ApplicationEventPublisher,监听ApplicationEvent 异步操作
有这么一个业务场景:当用户注册后,发送邮件到其邮箱提示用户进行账号激活,且注册成功的同时需要赠送新人用户体验卡券. 业务有了,那么问题也就来了. What? 问题....问题?我听说你有问题? 来拔刀 ...