IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离
IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离
参考
官方文档:oidc-client-js:oidc-client是一个JavaScript库,用于在浏览器(也可能是Cordova风格的应用程序)中运行。它为OIDC和OAuth2提供协议支持,并为用户会话和访问令牌管理提供管理功能。文档最后也给出了Angular2、Aurelia、ReactJS & Redux、Blog post on Angular这几种前端框架的示例。
JsOidc:使用oidc-client-js的客户端示例。
概念:隐式许可:简单描述过程以及适用范围。
Authorize Endpoint:主要介绍了请求过程参数含义。
三个Web站点:1、localhost:5000:认证服务器。2、www.jsclient.com:js纯静态客户端。3、localhost:5001:Api资源服务器。
认证服务端配置
认证服务ApiResource配置
new ApiResource("api1", "api项目 一")
{
ApiSecrets = { new Secret("api1pwd".Sha256()) }
},
认证服务Client配置
js client的静态资源服务端配置了host。
// JavaScript Client
new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true, RedirectUris = {
"http://localhost:5009/callback.html",
"http://www.jsclient.com/callback.html"
},
PostLogoutRedirectUris = {
"http://localhost:5009/index.html",
"http://www.jsclient.com/index.html"
},
AllowedCorsOrigins = {
"http://localhost:5009",
"http://www.jsclient.com"
}, AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
},
资源服务Api配置
资源服务器Startup配置
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//services.AddMvc();
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters(); services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false; options.ApiName = "api1";
options.ApiSecret = "api1pwd"; //对应ApiResources中的密钥
});
//支持跨域
services.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins("http://www.jsclient.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
Configure中添加 app.UseCors("default");
添加接口
[Route("[controller]")]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
var info = from c in User.Claims select new { c.Type, c.Value };
var list = info.ToList();
list.Add(new { Type = "api1返回", Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });
return new JsonResult(list);
}
}
Client客户端
1、JS Client
js Web-Hosted Client Resource的静态资源。

运行后效果如下:

页面中操作按钮如下:
<li><a class="btn btn-primary" href="index.html">Home</a></li>
<li><button class="btn btn-default request" data-scope='openid' data-type='id_token'>Login Only</button></li>
<li><button class="btn btn-default request" data-scope='openid profile' data-type='id_token'>Profile</button></li>
<li><button class="btn btn-default request" data-scope='openid profile api1' data-type='id_token token'>Profile and API Access</button></li>
<li><button class="btn btn-default request" data-scope='api1' data-type='token'>API Access Only</button></li>
<li><button class="btn btn-primary call">Call Service</button></li>
<li><button class="btn btn-info revoke">Revoke Access Token</button></li>
<li><button class="btn btn-info logout">Logout</button></li>
id_token:请求一个身份令牌(只允许身份范围)。
token:请求访问令牌(只允许资源作用域)。
id_token token:请求身份令牌和访问令牌。
清楚这个几个概念后页面上的操作按钮就都比较好理解了。
app.js中的配置如下:
var config = {
authority: "http://localhost:5000/",
client_id: "js",
redirect_uri: window.location.origin + "/callback.html",
post_logout_redirect_uri: window.location.origin + "/index.html",
// if we choose to use popup window instead for logins
popup_redirect_uri: window.location.origin + "/popup.html",
popupWindowFeatures: "menubar=yes,location=yes,toolbar=yes,width=1200,height=800,left=100,top=100;resizable=yes",
// these two will be done dynamically from the buttons clicked, but are
// needed if you want to use the silent_renew
response_type: "id_token token",
//scope: "openid profile email api1 api2.read_only",
scope: "openid profile api1",
// this will toggle if profile endpoint is used
loadUserInfo: false,
// silent renew will get a new access_token via an iframe
// just prior to the old access_token expiring (60 seconds prior)
silent_redirect_uri: window.location.origin + "/silent.html",
automaticSilentRenew: true,
// will revoke (reference) access tokens at logout time
revokeAccessTokenOnSignout: true,
// this will allow all the OIDC protocol claims to be visible in the window. normally a client app
// wouldn't care about them or want them taking up space
filterProtocolClaims: false
};
Oidc.Log.logger = window.console;
Oidc.Log.level = Oidc.Log.DEBUG;
var mgr = new Oidc.UserManager(config);
mgr.events.addUserLoaded(function (user) {
log("User loaded");
showTokens();
});
mgr.events.addUserUnloaded(function () {
log("User logged out locally");
showTokens();
});
mgr.events.addAccessTokenExpiring(function () {
log("Access token expiring..." + new Date());
console.log("Access token expiring..." + new Date());
});
mgr.events.addSilentRenewError(function (err) {
log("Silent renew error: " + err.message);
});
mgr.events.addUserSignedOut(function () {
log("User signed out of OP");
mgr.removeUser();
});
登录完成后会请求GET /connect/checksession在页面内追加iframe,iframe只包含js维护一系列的events,认证信息会存储在Session Storage中。

automaticSilentRenew: true
时会在设置的AccessTokenLifetime过期前AccessTokenExpiringNotificationTime(默认60秒)通过当前留存的id_token去请求新的身份认证信息。
GET /connect/authorize?client_id=js&redirect_uri=http%3A%2F%2Fwww.jsclient.com%2Fsilent.html&
response_type=id_token%20token&
scope=openid%20profile%20api1&
state=d814b897efc249a0b2028355f6ce80e8&
nonce=fb555249154b43eea816a122a34b0119&
prompt=none&
id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjAzMTZkNWQwYTViNTgyYzc0NmJlMmVhZWU1MTg1NzhiIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTI3MDY2MTMsImV4cCI6MTUxMjcwNjkxMywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoianMiLCJub25jZSI6IjUwM2YyY2VhNzE5ZjRlMjc5N2EzNThlZDlhYTI0ZDkyIiwiaWF0IjoxNTEyNzA2NjEzLCJhdF9oYXNoIjoiSUJVbTU1dFhEd3VKUTVJNlRJUGI2ZyIsInNpZCI6IjAwOGU2N2E2MWY2MzY1MjA1OTU5MTJmODQ2ZDdhNTVkIiwic3ViIjoiMiIsImF1dGhfdGltZSI6MTUxMjcwNjYxMiwiaWRwIjoibG9jYWwiLCJhbXIiOlsicHdkIl19.bJA7ejtzhjfobADoTpoNghhT19a7cnCBDGHSXvTOUpHwb_1To84l0Lu2pcGtDFeWqpWUTUKcXseNaao6bR41N45A_xCCfFsCHvSJ9pG_l-3NWIqceU-Zy-6JVH3MupbQLw3fm0Swt2NdfrjQ5G7q-e2WSXezHxXUvHbD2-PLqTG8_Qcotl0pK7lizGgdHiYF4SQM-qMLvTSOF0FHwkqiusxwrbDjR33UFYX7xlvjYRMoRvnw10qQlOQFO_0cox8BqxC-rW3EOu7mXyfz8TLyLqBIp9hlss0sayBEzxr-G_WFczmN5sL2xFpXK9dizhONAKUP7gpUjfrwy0CLiWefRg
AccessTokenLifetime设置的是90秒,所以Access token expiring...的时间就是在获取新的id_token token信息后的31秒也就是过期前AccessTokenExpiringNotificationTime(默认60秒)。

获取token过程解析
登录获取token的过程就参考上一篇。
IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离的更多相关文章
- IdentityServer4之Implicit(隐式许可)
IdentityServer4之Implicit(隐式许可) 参考 官方文档:3_interactive_login .7_javascript_client 概念:隐式许可 认证服务端配置 认证服务 ...
- asp.net core IdentityServer4 实现 implicit(隐式许可)实现第三方登录
前言 OAuth 2.0默认四种授权模式(GrantType) 授权码模式(authorization_code) 简化模式(implicit) 密码模式(resource owner passwor ...
- Scala中的Implicit(隐式转换,隐式参数,隐式类)
文章来自:http://www.cnblogs.com/hark0623/p/4196452.html 转发请注明 代码如下: /** * 隐式转换 隐式参数 隐式类 */ //隐式转换 class ...
- (转)也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
原文链接:http://ued.taobao.org/blog/2014/04/full-stack-development-with-nodejs/ 随着不同终端(pad/mobile/pc)的兴起 ...
- 也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的NodeJS,试图 ...
- 基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离) 前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们 ...
- 从壹开始前后端分离 [ Vue2.0+.NetCore2.1] 二十六║Client渲染、Server渲染知多少{补充}
前言 书接上文,昨天简单的说到了 SSR 服务端渲染的相关内容<二十五║初探SSR服务端渲染>,主要说明了相关概念,以及为什么使用等,昨天的一个小栗子因为时间问题,没有好好的给大家铺开来讲 ...
- 从零开始搭建django前后端分离项目 系列五(实战之excel流式导出)
项目中有一处功能需求是:需要在历史数据查询页面进行查询字段的选择,然后由后台数据库动态生成对应的excel表格并下载到本地. 如果文件较小,解决办法是先将要传送的内容全生成在内存中,然后再一次性传入R ...
- 海纳百川无所不容,Win10环境下使用Docker容器式部署前后端分离项目Django+Vue.js
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_179 随着现代化产品研发的不断推进,我们会发现,几乎每个产品线都会包含功能各异的服务,而且服务与服务之间存在也会存在着错综复杂的依 ...
随机推荐
- 做IT,必备的安全知识!
以前的认知 以前刚接触IT行业,而我身为运维,我以为我所需要做的安全就是修改服务器密码为复杂的,ssh端口改为非22,还有就是不让人登录服务器就可以保证我维护的东西安全. 现在的认知 工作也好几年了, ...
- 《团队作业第三、第四周》五小福团队作业--Scrum 冲刺阶段--Day7
<团队作业第三.第四周>五小福团队作业--Scrum 冲刺阶段--Day7 一.项目燃尽图 二.项目进展 [20172301郭恺第七天的进展] 第七天完成的任务: 代码整合,界面调整为相对 ...
- MYSQL可调用执行自定义SQL的代码
DELIMITER $$ USE `mysql_wispeed01`$$ DROP PROCEDURE IF EXISTS `sp_execSQL`$$ CREATE DEFINER=`sa`@`%` ...
- 数据分析 大数据之路 六 matplotlib 绘图工具
散点图 #导入必要的模块 import numpy as np import matplotlib.pyplot as plt #产生测试数据 x = np.arange(1,10) y = x ...
- 创建一个git仓库
1.git init 使用git init命令初始化一个git仓库,git仓库会生成一个.git目录 git init 1.使用指定的目录作为我们的git仓库 git init newrepo 2.初 ...
- word文档最上面有一条不是页眉的线
word2013文档最上面有一条不是页眉的线 在编辑Word文档时发现文档上面出现了一条实线,而且并非页眉,这里我采取了一个方式: 找到[设计]---[页面边框] 找到[边框和底纹]----[页面边框 ...
- linux crontab 执行mysqldump全局备份为空
今天遇到个问题,在定时备份时 去查看备份文件,发现大小竟然为0,执行 备份sh文件备份, 备份的sql文件大小正常.试了几种办法. 最终解决办法: 问题原因: 因为我设置的环境变量 就直接在sh中 使 ...
- 转发 Learning Go — from zero to hero
原文:https://medium.freecodecamp.org/learning-go-from-zero-to-hero-d2a3223b3d86 Learning Go — from zer ...
- ActiveMQ队列、主题模式区别
1.ActiveMQ队列模式如下图,生产者创建消息到消息中间件,再“均分给消费者”. 2.ActiveMQ主题模式如下图,生产者创建消息到消息中间件,消费者会接受到订阅的主题中所有的消息.在主题模式下 ...
- [LeetCode] Advantage Shuffle 优势洗牌
Given two arrays A and B of equal size, the advantage of A with respect to B is the number of indice ...