前言

上一篇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. 【Flutter 1-16】Flutter手把手教程UI布局和Widget——容器控件Container

    作者 | 弗拉德 来源 | 弗拉德(公众号:fulade_me) Container 我们先来看一下Container初始化的参数: Container({ Key key, // 位置 居左.居右. ...

  2. 发送微信通知 java 实现

    /实现类 @Service public class WeChatServiceImpl implements IWeChatService { @Override public WeChatSend ...

  3. 读取平台管理员xlsx文件

    package com.cn.peitest.excel; import java.io.File; import java.io.FileInputStream; import java.io.Fi ...

  4. [NOIP2013 提高组] 货车运输

    前言 使用算法:堆优化 \(prim\) , \(LCA\) . 题意 共有 \(n\) 个点,有 \(m\) 条边来连接这些点,每条边有权值.有 \(q\) 条类似于 \(u\) \(v\) 询问, ...

  5. springmvc 统一处理异常

    1.自定义统一异常处理器 自定义Exception实现 HandlerExceptionResolver接口或继承AbstractHandlerExceptionResolver类 1.实现接口Han ...

  6. 基于websocket的netty demo

    前面2文 基于http的netty demo 基于socket的netty demo 讲了netty在http和socket的使用,下面讲讲netty如何使用websocket websocket是h ...

  7. Asp.net Core 2.0 实现Cookie会话

    与1.0版本相比微软做了一些调整.详细请参考官方文档,我这里就讲2.0的吧 1.首先要在 根目录下 Startup.cs 类中启用 cookie会话,有两处要配置 第一处在  public void ...

  8. 冷饭新炒:理解Redisson中分布式锁的实现

    前提 在很早很早之前,写过一篇文章介绍过Redis中的red lock的实现,但是在生产环境中,笔者所负责的项目使用的分布式锁组件一直是Redisson.Redisson是具备多种内存数据网格特性的基 ...

  9. 【Nginx学习笔记】-初识Nginx

    Nginx 目录 Nginx Nginx 特点 Nginx 基本功能 Nginx 使用场景 Nginx 安装/卸载 Docker 方式运行 Ubuntu上安装 卸载Nginx Nginx 命令 Ngi ...

  10. LeetCode105 从前序和中序序列构造二叉树

    题目描述: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9 ...