博客与笔记无法实时同步, 笔记最新链接

OAuth 2.0

定义:OAuth 2.0是一个开放授权标准:允许资源所有者(用户)授权第三方应用访问该用户在某服务上的特定私有资源,但不提供账号密码给第三方应用。

安全提示:授权码和所有令牌必须通过Tsl加密传输。进入OAuth 2.0官网

OAuth 2.0协议流程图

  1. +--------+ +---------------+
  2. | |--(A)- Authorization Request ->| Resource |
  3. | | | Owner |
  4. | || Authorization |
  5. | Client | | Server |
  6. | || Resource |
  7. | | | Server |
  8. | |
  9. 授权码模式

  10. 授权码模式:code的生命周期必须短暂、或者只能单次使用,如果code被多次使用,授权服务器必须使该code生成的所有令牌失效。访问令牌由client后端保存。
  11.      +----------+
  12.      | Resource |
  13.      |   Owner  |
  14.      |          |
  15.      +----------+
  16.           ^
  17.           |
  18.          (B)
  19.      +----|-----+          Client Identifier      +---------------+
  20.      |         -+----(A)-- & Redirection URI ---->|               |
  21.      |  User-   |                                 | Authorization |
  22.      |  Agent  -+----(B)-- User authenticates --->|     Server    |
  23.      |          |                                 |               |
  24.      |         -+----(C)-- Authorization Code ------(D)-- Authorization Code ---------'      |
  25.      |  Client |          & Redirection URI                  |
  26.      |         |                                             |
  27.      |         |
  28. 简化模式

  29. 要点:不支持刷新令牌,访问令牌编码在Url中,所以会有暴露的风险(在Oauth2.0官网中已经不推荐使用)
  30.      +----------+
  31.      | Resource |
  32.      |  Owner   |
  33.      |          |
  34.      +----------+
  35.           ^
  36.           |
  37.          (B)
  38.      +----|-----+          Client Identifier     +---------------+
  39.      |         -+----(A)-- & Redirection URI --->|               |
  40.      |  User-   |                                | Authorization |
  41.      |  Agent  -|----(B)-- User authenticates -->|     Server    |
  42.      |          |                                |               |
  43.      |          ||   Web-Hosted  |
  44.      |          |          without Fragment      |     Client    |
  45.      |          |                                |    Resource   |
  46.      |     (F)  |
  47. 资源所有者密码模式

  48. 用户将用户名及密码提供给可信任的第三方应用,第三方应用向令牌终结点请求令牌。常用于第一方应用进行登陆. 优点:应用不需要存储用户账号、密码,通过刷新令牌保持持久登陆,降低密码泄露的风险。
  49.      +----------+
  50.      | Resource |
  51.      |  Owner   |
  52.      |          |
  53.      +----------+
  54.           v
  55.           |    Resource Owner
  56.          (A) Password Credentials
  57.           |
  58.           v
  59.      +---------+                                  +---------------+
  60.      |         |>--(B)---- Resource Owner ------->|               |
  61.      |         |         Password Credentials     | Authorization |
  62.      | Client  |                                  |     Server    |
  63.      |         |
  64. #请求token
  65. Request:
  66.     POST /connect/token HTTP/1.1
  67.     Host: idsrv-server.com
  68.     Content-type: application/x-www-form-urlencoded
  69.     body:
  70.     {
  71.         grant_type:password
  72.         username:dd
  73.         password:dd
  74.         client_id:eshopOnVue
  75.         scope:orders(可选参数)
  76.     }
  77. #请求刷新令牌:原刷新令牌失效、之前颁发的access_token不受影响(需要实现手动失效)
  78. Request:
  79.     POST /connect/token HTTP/1.1
  80.     Host: idsrv-server.com
  81.     Content-type: application/x-www-form-urlencoded
  82.     body:
  83.     {
  84.         grant_type:refresh_token
  85.         refresh_token:e4364377ec69c8d5c06a49d7b74efbd2a29015ac37e9ede8e17597d348931d32
  86.         client_id:eshopOnVue
  87.     }
  88. Respose:
  89. {
  90.     "id_token": "eyJhbGciO.iJSUzI1NiI.sImtpZCw",
  91.     "access_token": "eyJhb.GciOiJSUz.I1NiIsIm",
  92.     "expires_in": 3600,
  93.     "token_type": "Bearer",
  94.     "refresh_token": "60e7dda6e30473ce6dc0a1656b38c174a74ef73310d"
  95. }
  96. #通过access_token请求用户终结点(需要scope:profile):/connect/userinfo
  97. 客户端凭证模式

  98. 客户端直接使用自身的凭证向授权服务器终结点请求访问令牌。只能用于可信的客户端。不支持刷新令牌、无法访问用户资源scope(openid、profile、email等)

  99.      +---------+                                  +---------------+
  100.      |         |                                  |               |
  101.      |         |>--(A)- Client Authentication --->| Authorization |
  102.      | Client  |                                  |     Server    |
  103.      |         |
  104. Request:
  105.     POST /connect/token HTTP/1.1  #请求方式只能为post
  106.     Host: idsrv-server.com
  107.     Content-type: application/x-www-form-urlencoded #参数只能放在body里面
  108.     body:
  109.     {
  110.         grant_type:client_credentials
  111.         client_id:ClientCredentials
  112.         client_secret:iwiaXNzIjoibnVsbCIsImF1ZCI6WyJudWxsL3Jlc291cmNlcyIsIm9yZGVycyJdLCJjbGllbnRfaWQiOiJDb
  113.         scope:orders openid(可选,默认请求所有scope)
  114.     }
  115. Response:
  116.     HTTP/1.1 200 OK
  117.     Content-Type: application/json
  118.     Cache-Control: no-store
  119.     Pragma: no-cache
  120.     {
  121.       "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
  122.       "token_type":"bearer",
  123.       "expires_in":3600
  124.     }
  125. OpenID Connect(OIDC)

  126. 定义:它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议

  127. OIDC协议流程图

  128. +--------+                                   +--------+
  129. |        |                                   |        |
  130. |        |---------(1) AuthN Request-------->|        |
  131. |        |                                   |        |
  132. |        |  +--------+                       |        |
  133. |        |  |        |                       |        |
  134. |        |  |  End-  ||        |
  135. |        |  |  User  |                       |        |
  136. |   RP   |  |        |                       |   OP   |
  137. |        |  +--------+                       |        |
  138. |        |                                   |        |
  139. |        ||        |
  140. |        |                                   |        |
  141. |        |
  142. OIDC在OAuth之上的扩展

    • [ ] Scope:openid(用来区分这是一个OIDC的Authentication请求,而不是OAuth2的Authorization请求)
    • [ ] response_type:id_token,在implicit模式下请求id_token
    • [ ] id_token:身份令牌,是一个授权服务器提供的包含用户信息(由一组Cliams构成以及其他辅助的Cliams)的JWT格式的数据结构
    • [ ] UserInfo Endpoint:通过id_token从用户信息终结点获得一组EU相关的Claims,比如可以将Claims从token移除,避免token过大,只保留sub,通过UserInfo Endpoint查询Claims
  143. "response_type"参数值
  144. OIDC授权类型
  145. code
  146. Authorization Code Flow
  147. id_token token
  148. Implicit Flow
  149. code id_token
  150. Hybrid Flow
    • Authorization Code Flow:从授权终结点返回code,从令牌终结点返回token
    • Implicit Flow:从授权终结点返回所有token
    • Hybrid Flow:id_token返回给前端,access_token在后端保存(access_token的安全性要求比id_token)高
  151. JSON Web Token

  152. 定义:JWT是一个定义一种紧凑的,自包含的并且提供防篡改机制的传递数据的方式的标准协议
  153. JWT格式组成

  154. JWT由3部分构成:header.payload.signature
  155. 在IdSrv中,payload中的键值对根据token类型和授权流程的不同有所区别
  156. header:
  157. {
  158.   "alg": "RS256",//签名算法
  159.   "kid": "9dcf733a1192a6da053e64c6ee22ff87",
  160.   "typ": "JWT"//token类型
  161. }
  162. payload://需要传递的数据
  163. {
  164.   "nbf": 1556591630,//该jwt在此之前无效
  165.   "exp": 1556595230,//该jwt在此之后无效
  166.   "iss": "http://localhost:7102",//jwt颁发者
  167.   "iat": 1516239022,//jwt颁发时间
  168.   "aud": "http://localhost:7102/resources",//jwt接收者
  169.   "client_id": "jsImplicit",
  170.   "sub": "SubjectId",//用户唯一id
  171.   "auth_time": 1556591629,//授权时间
  172.   "idp": "local",//identityProvider
  173.   "name": "Username",
  174.   "scope": [
  175.     "openid",
  176.     "profile"
  177.   ],
  178.   "amr": [
  179.     "pwd"//authenticationMethod
  180.   ]
  181. }
  182. signature://token生成方使用私匙生成token,token消费方使用用公匙验证token是否被修改过
  183. RSASHA256(
  184.   base64UrlEncode(header) + "." +base64UrlEncode(payload),Public Key,Private Key
  185.   )
  186. #RSA签名过程
  187. #1.将消息内容进行base64编码:base64UrlEncode(header) + "." +base64UrlEncode(payload)
  188. #2.对编码后的内容进行SHA256哈希计算(不可逆)
  189. #3.对hash值使用privateKey加密,加密后内容作为签名
  190. #4.token接收方通过publicKey对签名进行解密得到hash值,并将内容进行hash计算,比较两个hash值,确保消息未被篡改
  191. expires_in="exp"-"nbf"
  192. RSA非对称加密算法

  193. 1 RSA算法特点:
  194. 1.1 公钥私钥对等,可以互换
  195. 1.2 私钥需要保存在可靠方
  196. 1.3 无法从公钥计算出私钥(理论上从私钥也无法计算出公钥,例外:openssl的公钥e固定为65537,且私钥文件中含有额外的参数,可以从私钥计算出公钥)
  197. 2 RSA应用
  198. 2.1 加密:消息发送方:公钥加密=>消息接收方:私钥解密(用于加密传递消息)
  199. ##缺点:无法防止伪造消息
  200. 2.2 签名:消息发送方:私钥加密=>消息接收方:公钥解密(用于消息签名,防止消息被篡改)
  201. ##缺点:消息明文传输
  202. HTTPS简单流程

  203. 1.服务器通过非对称算法生成私钥公钥
  204. 2.服务方将公钥提供给相关机构(CA)
  205. 3.CA生成证书并颁发给服务器:
  206. {
  207.     证书发布机构CA
  208.     证书有效期
  209.     公钥
  210.     证书所有者
  211.     签名(签名方法与JWT类似,私钥属于CA)
  212.     ...
  213. }
  214. 4.服务器将证书发送给客户端:
  215. {
  216.     1.TCP三次握手
  217.     2.建立tunnel
  218.     3.client hello(包括SessionId,可以避免重新握手,并重新使用已有对话密钥)
  219.     4.server hello
  220.     5.发送Certificate给客户端
  221. }
  222. 5.客户端通过系统中内置的CA公钥验证证书的合法性
  223. 6.客户端通过服务方公钥与服务器协商对称加密算法与密钥
  224. 7.进行对称加密通信
  225. 参考:https://zhuanlan.zhihu.com/p/22142170 https://zhuanlan.zhihu.com/p/27395037

  226. IdentityServer4

  227. 授权码模式

  228. PKCE(Proof Key for Code Exchange)

  229. 利用不可逆算法,确保在被窃取了授权码或其他密匙的情况下,也无法向授权服务器换取访问令牌

  230. PKCE流程:
  231. 1.客户端随机生成一串字符:
  232. {
  233.     code_verifier=base64url(RandomString),
  234.     code_challenge=base64url(sha256(code_verifier))
  235. }
  236. 2.客户端携带code_challenge向授权服务器发起授权请求
  237. 3.授权服务器对客户端进行认证成功后返回授权码,并保存code_challenge
  238. 4.客户端获取到授权码之后,携带code_verifier向令牌终结点发起请求,换取Access Token
  239. 5.授权服务器验证授权码,将code_verifier进行sha256计算并url编码后与code_challenge对比,如果一致,颁发访问令牌
  240. 参考:https://tonyxu.io/zh/posts/2018/oauth2-pkce-flow/

  241. 授权码模式流程

  242. #Step 1 客户端向授权服务器授权终结点发起请求:
  243.     GET /connect/authorize HTTP/1.1
  244.     Host: Idsrv.com,
  245.     Query String Parameters:
  246.     {
  247.         client_id: Swagger_UI
  248.         redirect_uri: http://localhost:9528/Callback
  249.         response_type: code
  250.         scope: openid profile orders
  251.         state: 668ae852a74f4923ad140d79d2f10fee
  252.         code_challenge: i2CnOeIHTBZZrAsgzEZV3-KpMTb_OCvl05ydETjrqIc
  253.         code_challenge_method: S256
  254.     }
  255. state:客户端随机生成的字符串,授权服务器在重定向到redirect_uri时会原样返回,客户端检查state是否相同,来防止CSRFF攻击
  256. #step 2 授权服务器对客户端进行认证,认证成功,授权服务器返回302重定向并携带ReturnUrl参数:
  257. Response:
  258. {
  259.     Status Code: 302 Found,
  260.     Location: http://localhost:6102/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DSwagger_UI%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A9528%252FCallback%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520orders%26state%3D668ae852a74f4923ad140d79d2f10fee%26code_challenge%3Di2CnOeIHTBZZrAsgzEZV3-KpMTb_OCvl05ydETjrqIc%26code_challenge_method%3DS256
  261. }
  262. #step 3 /Account/Login请求返回登陆页面,并将ReturnUrl写入登陆页面
  263. #step 4 用户在登陆页面发起登陆请求:
  264. 参数:
  265. {
  266.     1.用户名
  267.     2.密码
  268.     3.ReturnUrl
  269. }
  270. #step 4 授权服务器验证用户名、密码成功,且ReturnUrl有效:
  271. {
  272.     1.通过HttpContext.SignInAsync为当前请求上下文颁发登陆凭证:
  273.     Set-Cookie:
  274.     {
  275.         idsrv.session:'8c9e9e80f92da2551c77dc6ab03c69ca,path=/'
  276.         idsrv:'CfDJ8IOXoUULE4dDgZ02v48m533Xg,expires=Mon,08 Jul 2019 08:38:26 GMT, path=/,httponly'
  277.     }
  278.     2.发起重定向到ReturnUrl
  279. }
  280. #step 5 在 /connect/authorize/callback 终结点:
  281. {
  282.     授权服务器更新Cookie:idsrv,并重定向到redirect_uri,携带以下参数:
  283.     {
  284.         code: 21a9deaac4457e29f669a91bb36795c048aae5680b49ae3a1ffafa50aff0d169
  285.         scope: openid profile orders
  286.         state: 668ae852a74f4923ad140d79d2f10fee
  287.         session_state: ZcDaWfAmzNGLsXS3-1ofTvNGryU-KxeurTpPLxP6oF0.89cd4e2083165f0701dbd2181ede5b7b(会话状态)
  288.     }
  289. }
  290. #step 6 在redirect_uri向令牌终结点请求访问令牌:
  291. POST /connect/token HTTP/1.1
  292. Host: Idsrv.com,
  293. Content-type: application/x-www-form-urlencoded
  294. body:
  295. {
  296.     client_id: Swagger_UI
  297.     code: 21a9deaac4457e29f669a91bb36795c048aae5680b49ae3a1ffafa50aff0d169
  298.     redirect_uri: http://localhost:9528/Callback
  299.     code_verifier: dde8c25afc8d42728225154fea0aa098556671d3344c423f9007f1895b47dbf2be2116c7c5f34720842383ec9a7e0a66
  300.     grant_type: authorization_code
  301. }
  302. #step 7 授权服务器验证code和code_verifier,并颁发访问令牌
  303. 刷新访问令牌

  304. 配置new Oidc.UserManager()时 设置scope=offline_access,直接通过刷新令牌请求访问令牌。offline_access优先于silent_redirect_uri

  305. 通过Iframe页面进行静默刷新:
  306. #step 1 通过Iframe页面向授权终结点发起请求:
  307.     GET /connect/authorize HTTP/1.1
  308.     Host: Idsrv.com,
  309.     Cookie:
  310.     {
  311.         idsrv.session=8c9e9e80f92da2551c77dc6ab03c69ca;
  312.         idsrv=CfDJ8IOXoUULE4dDgZ02v48m53JzoKhJcuEwwXcdvHRYodIZ2nTuD
  313.     }
  314.     Query String Parameters:
  315.     {
  316.         client_id: Swagger_UI
  317.         redirect_uri: http://localhost:9528/SilentCallback
  318.         response_type: code
  319.         scope: openid profile orders
  320.         state: 54207b37bb644f90800d0993d5a5c210
  321.         code_challenge: 8bOHunvRggEM9m3Hwb-8m24KIiRV9rPSbz0OOvTP7D0
  322.         code_challenge_method: S256
  323.         prompt: none
  324.         id_token_hint: eyJhbGciOiJSUzI1NiIsImtp2UFyLw
  325.     }
  326. id_token_hint://为之前获取的id_token
  327. prompt:none//用来指示授权服务器是否引导用户重新认证和同意授权
  328. #step 2 重定向到redirect_uri,携带以下参数:
  329. {
  330.     code: a956650cd653debe11989d225c2caa2619521b9176b444fbcc83d3a1663bf1ed
  331.     scope: openid profile orders
  332.     state: 54207b37bb644f90800d0993d5a5c210
  333.     session_state: SGmLH8gIy6VAPtdlT6_zQtix_VM229bPkpY0OpwQ6fc.229a9d1e0be856145c035db0aa6033cc
  334. }
  335. #step 3 在redirect_uri页面执行new Oidc.UserManager().signinSilentCallback()
  336. #step 4 向令牌终结点请求访问令牌
  337. 登出操作:
  338. Js客户端mgr.signoutRedirect()
  339. 1.向IdSrv请求/connect/endsession 并携带以下两个参数
  340. id_token_hint:
  341. post_logout_redirect_uri: 登出回调地址
  342. 2.重定向到/Account/Logout 并携带生成的logoutId参数
  343. 3.在Logout里清除await HttpContext.SignOutAsync() 并跳转到post_logout_redirect_uri
  344. 资源所有者密码模式

  345. 											

    IdentityServer4笔记整理(更新中)的更多相关文章

      1. 微信小程序练习笔记(更新中。。。)
      1. 微信小程序练习笔记 微信小程序的练习笔记,用来整理思路的,文档持续更新中... 案例一:实现行的删除和增加操作  test.js // 当我们在特定方法中创建对象或者定义变量给与初始值的时候,它是局部 ...

      1. vue-学习笔记(更新中...)
      1. vue学习笔记 2017-08-23  11:10:28 Vue实例: var vm = new Vue({ // 选项 }) 实例化Vue.Vue实例,构造函数Vue.创建一个Vue的根实例,Vue ...

      1. 保姆级尚硅谷SpringCloud学习笔记(更新中)
      1. 目录 前言 正文内容 001_课程说明 002_零基础微服务架构理论入门 微服务优缺点[^1] SpringCloud与微服务的关系 SpringCloud技术栈 003_第二季Boot和Cloud版 ...

      1. 《Java并发编程实战》读书笔记(更新中)
      1. 一.简介 1.多线程编程要注意的几点: 安全性:永远不发生糟糕的事情 活跃性:某件正确的事情最终会发生(不会发生无限循环或者死锁) 性能:正确的事尽快发生(上下文切换消耗之类的) 二.线程安全 1.为 ...

      1. 《深入理解Java虚拟机:JVM高级属性与最佳实践》读书笔记(更新中)
      1. 第一章:走进Java 概述 Java技术体系 Java发展史 Java虚拟机发展史 1996年 JDK1.0,出现Sun Classic VM HotSpot VM, 它是 Sun JDK 和 Ope ...

      1. react-navigation 使用笔记 持续更新中
      1. 目录 基本使用(此处基本使用仅针对导航头部而言,不包含tabbar等) header怎么和app中通信呢? React-Navigation是目前React-Native官方推荐的导航组件,代替了原用 ...

      1. Python面试题整理-更新中
      1. 几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

      1. JS-JavaScript类库整理 [更新中...]
      1. 老大.jQuery插件库 ——收集最全最新最好的jQuery插件 http://www.jq22.com/ 一.Moment.js ——JavaScript 日期处理类库 http://momentj ...

      1. css:使用笔记(不断更新中...)
      1. 1,inline-block Inline :1是不支持宽高的 2 在一行内显示 span 啥的~ Block:1,占一行 2支持宽高 但是img因为在一行并排显示,我们归为行(内嵌)元素,但支持设置 ...

    1. 	
    2. 随机推荐

        1. TCP/IP协议、三次握手、四次挥手
        1. 1.什么是TCP/IP协议 TCP/IP 是一类协议系统,它是用于网络通信的一套协议集合. 传统上来说 TCP/IP 被认为是一个四层协议 1) 网络接口层: 主要是指物理层次的一些接口,比如电缆等. ...

        1. 开源SFTP客户端 WinSCP v5.13.5 Build 8967 绿色便携版
        1. 下载地址:点我 基本介绍 WinSCP 是一款可以在微软 Windows 系统环境下使用的支持 SSH 命令的开源图形化 SFTP 客户端工具.同时也支持 SCP 文件传输协议,它的主要功能是在本地与 ...

        1. SpringBoot基于数据库实现简单的分布式锁
        1. 本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...

        1. py+selenium+IE10【IE已停止工作】【已解决】
        1. 问题:跑自动化时,到某个用例IE就崩,提示已停止工作.   手工跑的时候,IE挂,提示“Internet Explorer 已经为了帮助保护您的计算机而关闭此网页”. 且每次都在需要调用flash插件 ...

        1. 最好的导航分割栏,分割线,实现底部透明,纯css
        1. <div class="Ui_Ct_Line padding_5"> <div>为您推荐</div> </div> .Ui_Ct_L ...

        1. [Spring-Cloud-Alibaba] Sentinel 整合RestTemplate & Feign
        1. Sentinel API Github : WIKI Sphu (指明要保护的资源名称) Tracer (指明调用来源,异常统计接口) ContextUtil(标示进入调用链入口) 流控规则(针对来源 ...

        1. java学习笔记(基础篇)—面向对象编程之封装、继承、多态
        1. 一. OOP中的基本概念 Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-Oriented Programming, OOP), 它允许设计者将面向对象设计实现为一 ...

        1. Fedora dnf配置
        1. 1.在配置文件/etc/dnf/dnf.conf中加入: fastestmirror=true keepcache=true 这样下载安装软件就快多了. 2.dnf常用命令 检查并升级可用软件包: $ ...

        1. Excel催化剂开源第8波-VSTO开发之异步调用方法
        1. 在VSTO开发过程中,因其和普通的Winform开发有点差别,具体细节笔者也说不清楚,大概是VSTO的插件是寄生在Excel中,不属于独立的进程之类的,其异步方法调用时,未能如Winform那样直接用 ...

        1. jenkins +Jmeter 完成分布式性能测试
        1. 1.Jmeter 压测机器配置. 下载Jmeter 版本:https://jmeter.apache.org/download_jmeter.cgi   我下的是5.1.1 将下载后的版本进行解压. ...

      1. 							
      2.