聊聊常见的服务(接口)认证授权
写在前面
头发掉得多了,总有机会接触/调到各种各样的接口,各种面向Api编程实际上已经嵌入到我们的习惯中,没办法现在服务端通信还得是http(s),其他协议还未能成为通用的。
大厂的开发平台api我先不敢说,各种小公司、或者不少大公司内部之间,各种各样的的接口签名/授权方式可以说是尽显劳动人民智慧、八仙过海,各显神通。当然,我也曾是八仙中一员大将;
然而,不能总当神仙,偶尔也要做下凡人。下面我们聊聊常见的服务授权方式;
Basic Auth
Basic Auth使用base64编码把 username
:password
(注意中间有个半角冒号)加密后放入请求头:
比如账号密码 hei:123 , base64后在request--header这样:
Authorization: Basic aGVpOjEyMw==
Postman支持
总结:
优点:简单明了,特别容易理解;
缺点:因为简单,且几乎是明文的形式传递,总得来说不够安全;且要配合权限啊、授权策略啊要花挺多成本;
看场景使用;
Key Auth
这个别看名字起得高大上,其实也就是你先定义一个 KeyName,KeyValue,调用方和接口定义方约定这个Key放在--header或者Query Params里,到时按约定好的取出就好;
比如我定义了的
KeyName: apikey
KeyValue: hei.key.7LimLB5qXHtuBsI7HpxM9mj447ME3GlNoe7WxKL5
约定好放到Header里。
Postman支持
总结: 跟basic auth 一样,还是不够安全,虽然可以通过添加超复杂的keyValue提高安全性。但记住,只要是固定的key,永远都是不安全的。看场景使用。
Jwt Auth
这个知识点可是可是博客园的常客了,三天两头都有相关博文;但毕竟本片不是jwt专题,我就不长篇阔论了简单聊聊;
首先jwt是啥
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),
传递信息的标准的说白了就是一种数据格式,它分成三个部分组成,中间用.
隔开:
(图来自龙哥的博客)
//上图三部分一般这样组成,所以整个jwt都是base64的(除了那两个分割的'.')
base64Url(Header)+"."+base64Url(Payload)+"."+base64Url(Signature)
具体的一个jwt
eyJhbGciOiJSUzI1NiIsImtpZCI6IjY1OTMxODE4QjYxQkIzQTVEMUIxN0Y0MEVCRTlEQkY2IiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTcxNDIxNzgsImV4cCI6MTU5NzE0OTM3OCwiaXNzIjoiaHR0cDovLzE3Mi4xNi4zLjExNzo1MTAwIiwiYXVkIjpbIm9jZWxvdCIsImh0dHA6Ly8xNzIuMTYuMy4xMTc6NTEwMC9yZXNvdXJjZXMiXSwiY2xpZW50X2lkIjoib2NlbG90LmNsaWVudCIsImp0aSI6IkQxRkExNkE3MkM1RDY4RDEyMTMzM0RGRjRDRDBCM0Q4IiwiaWF0IjoxNTk3MTQyMTc4LCJzY29wZSI6WyJvY2Vsb3QuYWRtaW4iXX0.PCN_Q77r0IyaesLy-Q0lTV12EYD9GkywrDMfxrCBj3ac9YltW8RzczAqdn2f92iysf_5Iu6hvTm16z9MJay6-eGWBiuIgJRXaCDlTqWWKcI8rWmW17ncyJT5oIgwip54Tfder9AfJOUJ-K0U2zT0fsrnBf7CZDLmkAAFHoxky1dzmPnh7JM4EkjtC-ybLOu_Aav7GgIOyYfodovxNgMvGHdhmheJLjxpjGblfI6o3rH8fRedwoV8zCY8MxJRGVcqg8slo0E9wfsebNx8hCV1mLHJbuDbJ1DCnDQ_1I1pFEFZCVNE2g0R-LRMC7opfFcveorNvZcJ8zEPWcACqoGXZg
我们 复制到https://jwt.io/ 解析看看:
可以很清楚的看到, header部分是说明Token的类型和所使用的算法,payload部分就是授权信息,比如用户名啊、哪个服务器,什么时候发的、什么时候失效等等。signature部分是签名信息,防止篡改。
一般是怎么用jwt的
我借龙哥个图来说明下
- 一般我们先定义一个颁发token服务(Auth Service --Api),服务调用方携带授权信息申请token;
- Auth Service验证授权信息后返回jwt;
- 服务调用方携带jwt请求受保护接口;
- 受保护接口验证jwt 的有效性,验证有没有权限、是否在有效期、有没有被篡改等(这里不用到Auth Service验,也就是去中心化的方式,这是jwt的一大有点)。这里写着是网关,其实也可以写在接口的过滤器那里,不过这样每个项目都要实现一遍验证逻辑了。
- 这里已经解析完jwt,打扰可以携带jwt的信息去调用接口啦;
- 响应,流程完;
其实大家都差不多这么用的,不管是自定义实现还是用第三方的中间件形式,具体看需求;
Postman支持
总结:
优点
- 因为json的通用性,所以JWT是可以进行跨语言支持;
- 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
- 便于传输,jwt的构成非常简单,传输字节不大,高性能。
- 去中心化,高性能;
缺点
- 安全性:如果是完全去中心化的方式,如果jwt给黑客截取了,是没有办法吊销的,开发的时候可以考虑下如何解决这个问题;
- 携带的信息是完全开放的,不能携带安全性高的加密信息,只能说有限安全性,依然看场景使用,不过我的经验,日常开发绝大部分时候够用了。
Oauth2--client_credentials(客户端凭证)模式
Oauth2.0 有多种模式,比如Authorization Code、Implicit Flow、Password Grant等、我们今天只来看client_credentials--客户端配置模式吧。
我们先看官方的流程图:
+---------+ +---------------+
| | | |
| |>--(A)- Client Authentication --->| Authorization |
| Client | | Server |
| |<--(B)---- Access Token ---------<| |
| | | |
+---------+ +---------------+
可以看到非常简单,他其实只要:
A、Client携带授权信息(client_id,client_scret,scopes,grant_type等)去Authorization Server 申领AccessToken;
B、Authorization Server 颁发AccessToken;
然后你就可以用这个AccessToken 调用 受保护的接口了;
我们来看看实例:
1、先请求AccessToken
2、携带AccessToken 调用受保护接口
Postman支持
其实这里的header是这样的:
Authorization: Bearer ZJg0rak2ZYKyZeBTH7zJzDl94AjkfwiE
那可以看到我们的AccessToken ,很明显很简短,看情况是不携带任何信息的。那意味着它每次调用都需要去Authorization Server验证AccessToken 才行,这样接口调用量瞬间翻倍了,性能肯定受影响。我们能不能像上面提到的jwt一样,用jwt 做token,去中心化呢?
答案是可以的,Oauth2.0-client_credentials模式本身是对流程的标准化,并没有限制token类型,所以我们是可以用jwt做token,但是又涉及到一个问题授权是OAth2.0的活,如果你加入jwt做身份区分那其实已经是OpenId Connect的活了,那又是另一个话题了。但那其实是一个非常好的设计,我们.net core里面就用这么个方案实现的框架IdentityServer4;
总结:identityserver4真香;
Hmac Auth
Hmac的全称是Hash-based Message Authentication Code(基于哈希的消息认证码), 看起来有点蒙,我们先来看个例子,比如我们有如下的接口地址:
http://api.hei.com?userid=23233&age=18&type=normal
我们经常会这样给我们接口加签名:
- 先把query参数全小写后,按a-z排序为,用&隔开:age=18&type=normal&userid=23233
- 对参数32位小写md5, md5_32(“age=18&type=normal&userid=23233”) 得到sign:a8b8a635cc34b95a8788abfa6f6b9ff2
- 把sign加在请求参数后面:http://api.hei.com?userid=23233&age=18&type=normal&sign=a8b8a635cc34b95a8788abfa6f6b9ff2
- 服务端按同样的方法验证参数;
如果我们把以上的 md5_32(“排序参数”)加“盐”改为:md5_32(my_secret_key,“排序参数”) 这就是:
Hmac-Md5 算法,同理,还有:
Hmac-SHA1
Hmac-SHA384
Hmac-SHA256
Hmac-SHA512
等等算法,主要的区别在于哈希算法的不同。因为安全性有一定的报障,各种语言里面都会有对应的语言无关的实现,比如.net core 里面就有:HMACMD5、HMACSHA1、HMACSHA256、HMACSHA384、HMACSHA512 这五个内置类,都是调用里面的ComputeHash()。
当然,生产中的例子可能不像上面的那么简单,比如接口调用方要求一定附加一个时间戳参数在请求里,5分钟内本请求有效,my_secret_key 非常复杂,动态 my_secret_key 等等方式。
这个Postman当然支持:
这是我用网关kong内置的Hmac Auth 插件实现的。
总结:
大总结
我觉得接口认证授权这块挺多东西,我现在用IdentityServer4+Hmac比较多,大家平时怎么处理的,也可以聊一聊~
参考
https://www.cnblogs.com/edisonchou/p/talk_about_what_is_jwt.html
- SpringBoot(四)之thymeleaf的使用
- SpringBoot(三)整合Redis
- 除了小蜗牛,我蛙还带来了YUNUCMSv1.0.6
- SpringBoot(二)Web整合开发
- SpringBoot(一)走进Springboot的世界
- RxJava2学习笔记(2)
- RxJava2学习笔记(1)
- Matplotlib新手上路(下)
- Matplotlib新手上路(中)
- 工具| sqlmap payload修改之路
- 利用java8对设计模式的重构
- 漏洞|74cms 3.6 前台SQL注入+Python脚本小练习
- Matplotlib新手上路(上)
- CentOS 7 搭建基于携程Apollo(阿波罗)配置中心单机模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 如何安装FreeIPA
- 编译及使用hive-testbench生成Hive基准测试数据
- 树酱的前端知识体系构建(下)
- Babel配置傻傻看不懂?
- Saltstack_使用指南10_配置管理-状态模块
- Saltstack_使用指南11_配置管理-状态之间依赖关系 4.1. 部署架构4.2. Apache和PHP的SLS【正向依赖】4.3. mariadb 的 SLS
- 前端工程化之CICD那点破事
- Saltstack_使用指南12_配置管理-jinja模板 4.1. 部署架构4.2. 本章涉及的 pillar 的信息4.3. 配置文件 httpd.conf 修改
- Saltstack_使用指南13_runner的job和manage与execution的saltutil 5.1. master执行5.2. 查看当前活动的jobs
- Saltstack_使用指南14_无master 3.1. 常规信息3.2. grains设置3.3. pillar设置
- 在CDH7.1.1中安装NiFi
- 重学前端(三)-聊聊我们的浏览器的那些事
- Saltstack_使用指南15_多master 3.1. 创建冗余的master3.2. 拷贝主master的key和配置到冗余的master3.3. 启动冗余ma
- Saltstack_使用指南16_syndic 3.1. 部署salt-master3.2. 其他配置与部署4.1. 部署salt-syndic4.2. syndic
- Centos7安装单机版MongoDB