前言

上一篇Resource Owner Password Credentials模式虽然有用户参与,但对于非信任的第三方的来说,使用这种模式是有风险的,所以相对用的不多;这里接着说说implicit隐式模式,这种模式比较适合于纯前端客户端,比如Vue、Angular、React项目等,相对来说整个流程比较安全,只需在认证服务器进行认证即可,无需在客户端进行相关隐私信息录入,但前提是要客户端保证安全,不然容易被别人钓鱼(安全很重要),那IdentityServer4不背这个锅。

正文

既然有用户参与,交互肯定少不了,认证那更不能缺少,所以这里使用OIDC(OpenID Connect)的协议进行用户身份验证;别跑,不管是客户端还是认证服务器端,已经都封装好了,拿过来直接用即可;

从流程先了解一下,直接上图:

流程简要说明:

  1. 用户通过浏览器(User-Agent)访问第三方客户端(Client);
  2. 如果客户端需要进行认证授权,则将其重定向到认证服务器(Authorization server);
  3. 用户(ResorceOwner)在认证服务器上进行认证;
  4. 认证服务器(Authorization server)验证成功之后,返回AccessToken和Id Token客户端;
  5. 后续用户再操作客户端的时候,若需访问保护资源,直接在请求中带上AccessToken即可;
  6. 最终资源服务器(Resource server)返回对应信息;

术语解释:

  • User-Agent:这里指就是浏览器;如果客户端是Web,就需要用户通过浏览器访问客户端,所以这里的浏览器就是User-Agent;
  • Id Token:标识用户身份的Token,这是OpenID Connect带上的。

知道大概的流程,接下来就通过代码实践的方式演示一把。

1.拷贝上一节Reource Owner Password的授权服务器和资源服务器代码并完善;

对于资源服务器来说,这里先暂时不用修改其他;

认证服务器增加界面支持

而认证服务器需要有自己的页面,因为在访问客户端时会重定向到认证服务器进行认证信息录入和授权相关操作,那页面需要自己写吗,不需要的,IdentityServer4模板中已经准备好了,如下操作:

通过以上两种方式都可以获取到以下文件,将其拷贝到认证服务器项目中,如下:

由于之前的认证服务器只是单纯API项目,不支持MVC,因为增加的界面是MVC页面,所以需要在Startup.cs中增加MVC的支持,页面中需要样式文件的加载,则同时需要增加静态文件处理,如下:

运行起来看效果,如下:

备案客户端

上面界面没问题了,这里打算做一个纯前端(Vue)的客户端进行测试,所以需要在认证服务器中提前将客户端进行备案,如下:

2. 增加纯前端客户端(Vue)

这里不打算使用脚手架工具去生成项目,为了不喧宾夺主,这里就很单纯的写html和Js,只是在其中引用Vue,用Vue的思路进行编码演示;

既然是个纯前端项目,得要有个服务器作为宿主,然后通过URL地址访问页面,这里不想用其他比较重的服务器,live-server简单好用,就用它了,简单搭建一下环境:

环境准备

我是用npm安装,所以需要安装nodejs,这里就不详细扩展了,具体安装步骤详见:https://www.runoob.com/nodejs/nodejs-install-setup.html;

有了nodejs环境,直接npm安装live-server,如下命令:

npm install -g live-server ###全局安装live-server,后续都可以用

安装完就可以直接使用了,直接在指定目录下执行live-server即可,默认端口是8080;

创建纯前端客户端

项目目录结构如下:

简要说明:

  • js目录:存放依赖的js;

    live-server-https目录是提供live-server启动时提供live-server-https支持,其实项目本身并不需要;后续如果需要将前端页面指定https访问,可以指定此库运行;

    oidc-client.js/oidc-client.min.js是用于前端客户端实现OpenID Connect,引入直接使用即可,也可以自行在网上下载(https://github.com/IdentityModel/oidc-client-js);

    vue.js提供vue的支持,虽然没用脚手架,但用vue还是没问题;

  • callback.html登录成功之后回调的页面,即当在认证服务器登录成功之后重定向客户端的页面;

  • index.html主页面,这里也用于登出时重定向的页面;

  • noauth.html无权限时跳转的页面;

代码主要集中在index.html,下面直接上代码吧,具体说明直接看注释吧;

index.html代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<button id="login" @click="login">Login</button>
<button id="api" @click="callApi">Call API</button>
<button id="logout" @click="logout">Logout</button>
<!-- 显示日志,包含登入、登出和请求API结果 -->
<pre id="results">{{results}}</pre>
</div>
<script src="./js/oidc-client.js"></script>
<script src="js/vue.js"></script>
<!-- <script src="./js/app.js"></script> -->
<script>
var vm = new Vue({
el: "#app",
created() {
// 根据配置信息创建用户管理对象,后续直接使用
this.mgr = new Oidc.UserManager(this.config);
},
mounted() {
// 这里要注意this的使用
var that = this;
this.mgr.getUser().then(function(user) {
if (user) { // 判断是否登录成功
that.log("User logged in", user.profile);
} else { // 没登录
that.log("User not logged in");
}
});
},
data: {
// 客户端配置
config: {
authority: "http://localhost:6100",
client_id: "JsClient",
redirect_uri: "http://localhost:8080/callback.html",
response_type: "id_token token",
scope: "openid profile orderApi", //客户端需要的权限范围
post_logout_redirect_uri: "http://localhost:8080/index.html",
},
mgr: null, //登录对象
results: "" //登录通过数据
},
methods: {
// 登录
login: function() {
console.log("login");
this.mgr.signinRedirect();
},
callApi: function() {
console.log("CallAPI");
var that = this;
// 先判断是否登录,登录之后在去调用API
this.mgr.getUser().then(function(user) {
var url = "http://localhost:5000/api/Order";
// 这里使用原生异步请求,就是引入第三方ajax库啦
var xhr = new XMLHttpRequest(); xhr.open("GET", url);
xhr.onload = function() {
// 显示请求API获取到的数据
that.log(xhr.status, JSON.parse(xhr.responseText));
};
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
// 发送请求
xhr.send();
});
},
logout: function() {
console.log("logout");
// 登出
this.mgr.signoutRedirect();
},
// 将信息展示
log: function() {
var that = this;
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);
}
that.results = msg + '\r\n';
});
}
}
});
</script>
</body>
</html>

callback.html代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script src="./js/oidc-client.js"></script>
<script>
new Oidc.UserManager().signinRedirectCallback().then(function() {
console.log("test");
// 如果登录成功就回到主页面
window.location = "index.html";
}).catch(function(e) {
console.log(e);
//没有权限就跳转到无权限页面
window.location="noauth.html";
});
</script>
</body>
</html>

noauth.html代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>
没权限
</div>
</body>
</html>

到这客户端的代码已经撸完了,直接进入JsClient目录,执行live-server即可:

如果使用http请求,执行live-server即可;

3.联合调试看效果

上一步已经将客户端启起来了,接下来把认证服务器和API资源服务器启动,看看效果:

  1. 点击Login进行登录,就会跳转到认证服务器进行验证,如下:

    到这一步,估计用其他浏览器没什么问题,会继续进行跳转;但如果用到谷歌最新的浏览器,这里就不会跳转,因为谷歌对Cookie进行整改,尽管输入正确的用户名和密码,也只是刷新一下,还是在登录页面,需要做一下处理,如下:

    新增一个处理类:SameSiteCookiesServiceCollectionExtensions.cs,代码内容就不贴啦,这是公开代码,大佬写好的解决方案;

    写好处理类之后,直接使用即可,如下:

    完成以上步骤,谷歌不能跳转的问题就解决啦; 继续往下走;

  2. 输入用户名和密码 Zoe/123456,点击登录,直接进入授权选择页面,如下:

    这个界面是不是比较熟,通常我们用微信、QQ或者是其他登录时,都会弹出一个授权页面选择授权内容。这个授权页面是可以控制不显示的,只需要在认证服务器备案客户端时设置属性即可,如下:

  3. 点击授权完成之后,就会重定向配置的callback.html页面,在callback.html代码中可以看到,如果判断用户已经登录,就直接转到index.html主页面,否则就转到noauth.html无权限页面,这里已经登录授权成功,肯定最终就转到index.html页面,如下:

  4. 点击CallAPI去调用受保护资源,内部是根据上一步得到AccessToken进行保护资源的访问;

    注意,这里资源服务器一定要进跨域配置,允许客户访问,在API资源服务器中进行如下配置:

    然后运行效果如下:

  5. 点击Logout登出,这里不截图了,小伙伴试试;

好吧,今天状态不佳,先到这,后续项目实战再好好说说。

源码地址:https://github.com/zyq025/IDS4Demo/tree/main/ImlicitDemo;

总结

Implicit模式使用思路差不多就是这样,但这种模式特别要注意项目本身安全,如数据传输过程被拦截,或网站本身容易被攻击,黑客通过钓鱼页面就容易获取隐私信息等,所以项目通常都强烈推荐https,降低数据传输过程被抓包的风险;而对于钓鱼等这种攻击,可以通过判断校验源IP等方式;安全的点很多,这里只是简单举例;下次说说Authorization Code(授权码)模式;

一个被程序搞丑的帅小伙,关注"Code综艺圈",跟我一起学~

IdentityServer4之Implicit和纯前端好像很配哦的更多相关文章

  1. IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离

    IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离 参考 官方文档:oidc-client-js:oidc-client是一个JavaScrip ...

  2. 纯前端表格控件SpreadJS以专注业务、提升效率赢得用户与市场

    提起华为2012实验室,你可能有点陌生. 但你一定还对前段时间华为的那封<海思总裁致员工的一封信>记忆犹新,就在那篇饱含深情的信中,我们知道了华为为确保公司大部分产品的战略安全和连续供应, ...

  3. JS魔法堂之实战:纯前端的图片预览

    一.前言 图片上传是一个普通不过的功能,而图片预览就是就是上传功能中必不可少的子功能了.在这之前,我曾经通过订阅input[type=file]元素的onchange事件,一旦更改路径则将图片上传至服 ...

  4. Web纯前端“旭日图”实现元素周期表

    一.什么是旭日图 旭日图是在Excel 2016中新增的一种图表.有些类似饼图,饼图的优势是可以显示占比.但是饼图只能显示单级数据.旭日图用来表示多层级数据的占比.旭日图以一种分层方式显示,非常适合用 ...

  5. Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(上篇——纯前端多页面)

    Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(上篇--纯前端多页面) @(HTML/JS) 一般来说,使用vue做成单页应用比较好,但特殊情况下,需要使用多页面也有另外 ...

  6. 纯前端导出pdf文件

    纯前端js导出pdf,已经用于生产环境. 工具: 1.html2canvas,一种让html转换为图片的工具. 2.pdfmake或者jspdf ,一种生成.编辑pdf,并且导出pdf的工具. pdf ...

  7. 微信授权、获取用户openid-纯前端实现——jsonp跨域访问返回json数据会报错的纯前端解决办法

    近来,倒霉的后台跟我说让我拿个openid做微信支付使用,寻思很简单,开始干活. 首先引导用户打开如下链接,只需要将appid修改为自己的就可以,redirect_url写你的重定向url https ...

  8. vue后台_纯前端实现excel导出/csv导出

    之前的文件下载功能一般是由前后端配合实现,由于项目需要,纯前端实现了一把excel的导出功能: 一.excel导出 1.安装依赖库 xlsx:这是一个功能强大的excel处理库,但是上手难度也很大,还 ...

  9. 从 .NET 到 JavaScript —— 纯前端报表控件 ActiveReportsJS 焕新登场

    报表工具的发展史,最早可以追溯到微软报表SSRS(SQL Server Reporting Services)时期.最初,报表工具主要应用于报表的定制.呈现和输出.经过几十年的发展,随着各种业务系统功 ...

随机推荐

  1. java斐波纳契数列

    //斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.-- 这个数列从第三项开始,每一项都等于前两项之和. public class DiGui { public ...

  2. Kafka体系架构、命令、Go案例

    原文地址:https://github.com/WilburXu/blog/blob/master/kafka/Kafka基本架构和命令.md Kafka体系架构 Broker服务代理节点 服务代理节 ...

  3. jit编译原理

    jit用以把程序全部或部分翻译成本地机器码,当需要装载某个类[通常是创建第一个对象时],编译器会先找到其.class文件,然后将该类的字节码装入内存. hotspot采用惰性评估法: 如果一段代码频繁 ...

  4. hive之Json解析(普通Json和Json数组)

    一.数据准备 现准备原始json数据(test.json)如下: {"movie":"1193","rate":"5", ...

  5. UML软件工程复习——用例图和类图

    ------------恢复内容开始------------ 软件产品开发流程是需求.分析.设计.实现. 面向对象三大特征:继承性,封装性.多态性 模型将软件生命周期划分为软件计划.需求分析和定义.软 ...

  6. 【.NET与树莓派】上手前的一些准备工作

    .NET Iot 不是什么新鲜事物,百科很强大,故老周在此也不必多介绍.现在的时代和老周当年学 QBasic 的时代不同,那时候拉根电话线上网,下载速度只有可怜的 3.5 kb/s.而且还要去店里买上 ...

  7. python的默认参数的一个坑

    前言 pass 正文 在 https://docs.python.org/3/tutorial/controlflow.html#default-argument-values 中,有这样一段话 Im ...

  8. 使用SpringBoot搭建Web项目

    序言 从简入深的使用SpringBoot搭建一个Web项目,同时也包括一些小的问题.第一篇博文是以较为简单的方式完成一个可以连接数据库的Springboot web程序.之前自己学习的时候看网上的教程 ...

  9. 【JDBC核心】commons-dbutils

    commons-dbutils 简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,它是对 JDBC 的简单封装,学习成本极低,并且使用 commons-d ...

  10. at定时任务

    1)at是只执行一次,执行完后任务删除.at的守护进程atd会以后台模式运行,检查作业队列来运行.2)默认 atd每60秒巡逻一次,有作业时候,检查作业时间,如果和当前时间一样,就执行任务3)在使用a ...