2021-08-20
- oAuth是一种授权机制,数据所有者告诉授权系统,允许第三方应用获取这些数据,授权系统从而产生一个短期的进入令牌(token),第三方应用通过令牌获取数据。
授权码方式
#
第三方应用(记为a)访问CALLBACK_URL这个网站,会重定向到授权系统(记为b),url如1所示
1. 请求授权码
#
https://b.com/oauth/authorize?
response_type=code& #表示参数要求返回授权码
client_id=CLIENT_ID& #客户端id,b就知道是谁在请求
redirect_uri=CALLBACK_URL& #b接收请求后跳转的网站
scope=read #授权范围
2. 返回授权码
#
在授权系统登录成功后,会重定向到CALLBACK_URL?code=AUTHORIZATION_CODE
,code就是授权码。
3. 请求令牌
#
CALLBACK_URL这个网站会重定向到授权系统,url如下:
https://b.com/oauth/token?
client_id=CLIENT_ID& #客户端id,b就知道是谁在请求
client_secret=CLIENT_SECRET&
grant_type=authorization_code& #授权类型,表明是授权码
code=AUTHORIZATION_CODE& #上一步拿到的授权码
redirect_uri=CALLBACK_URL #b之后跳转的网站
4. 返回令牌
#
授权系统会重定向到CALLBACK_URL,并发送一段JSON数据
{
"access_token":"ACCESS_TOKEN(令牌)",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{...}
}
参考链接:
OAuth 2.0 的四种方式 - 阮一峰的网络日志 (ruanyifeng.com)
2021-08-20
- 如何保证公钥不被篡改?将公钥放在数字证书中,只要证书是可信的,公钥就是可信的。
握手过程
#
1. 客户端发送请求(ClientHello)。
#
客户端向服务器提供以下信息:
- 支持的协议版本,如TLS1.0版本。
- 客户端生成的随机数,是之后生成会话密钥的一部分。
- 支持的加密算法,如RSA。
- 支持的压缩算法。
2. 服务器收到请求后,向客户端发出回应(ServerHello)。
#
服务器向客户端发出回应包含以下内容(如果服务器需要确认客户端的身份,就需要再包含一项请求,要求和护短提供证书文件):
- 确认使用的协议版本。
- 服务器生成的随机数,是之后生成会话密钥的一部分。
- 确认使用的加密算法。
- 服务器证书。
3. 客户端回应
#
客户端收到回应后,先验证服务器的证书,如果证书不是可信机构颁发、证书中的域名与实际域名不一致、证书已经过期,就会显示一个警告询问是否继续。如果继续或者证书没有问题,客户端向服务端发送以下内容:
- 一个随机数(pre-master key),该随机数用服务器的公钥加密。
- 编码改变通知,表示随后的信息都用协商的加密算法和密钥发送。
- 客户端的握手结束通知,包含前面发送所有内容的hash值,供服务器校验。
4. 服务器回应
#
服务器收到第三个随机数后,计算会话使用的“会话密钥”,向客户端发送以下信息:
- 编码改变通知,表面之后的信息都用协商的加密算法和密钥发送。
- 服务器握手状态结束通知,包含签名发送的所有内容的hash值。
- 中间人攻击:如果中间人在客户端与服务端开始建立连接的时候,拦截客户端的请求,让客户端与自己通信,自己再和服务端通信,出现了:客户端请求->中间人->服务端,服务端响应->中间人->客户端,中间人能获取到客户端请求的所有数据和服务端响应的所有数据。所以当出现证书不安全的时候要注意。
参考链接:
SSL/TLS协议运行机制的概述 - 阮一峰的网络日志 (ruanyifeng.com)
2021-08-20
- 全称是JSON Web Token。
- jwt由下面三个部分组成,格式类似
aaa.bbb.ccc
- Header(头部)
- Payload(负载)
- Signature(签名)
- Header部分是一个JSON对象,由签名算法和token类型组成,会使用用Base64URL加密,加密后的数据组成jwt的第一部分。原始数据如下(例):
{
"alg":"HS256",
"typ":"JWT"
}
- Payload也是一个JSON对象,会用Base64URL加密,加密后的数据组成jwt的第二部分。默认定义了一些参数 iss(ssuer):签发人,exp(expiration):过期时间,sub(subject):主题,aud(audience):受众,nbf(not before):生效时间,iat(issued at):签发时间,jti(jwi id):编号。原始数据如下(例):
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
- Signature会根据服务端的密钥和Header中给的算法,对加密后的Header和加密后的Payload再次进行加密,将加密的结果组成jwt的第三部分。加密的逻辑如下:
HMACSHA256( base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
- 可以在HTTP的headers中的使用,这样就不会有跨域问题了(因为没有使用cookie):
Authorization:Bearer <token>
参考链接:
JSON Web Token Introduction - jwt.io
参考链接:
JSON Web Token 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)
解密jwt:
JSON Web Tokens - jwt.io
2021-08-19

CAS协议
#
- central authentication service(中央认证服务),TGT(Ticket Grangting Ticket)。TGC(ticket-granting cookie)、ST(service ticket)
- 流程如下(所有的过程都是重定向):
- 用户通过浏览器访问业务系统(就是CAS client,可能是某个微服务)。
- 业务系统重定向到CAS server。
- server对用户进行认证,如用户提供了正确的认证信息,server就会创建对应的session(似乎就是TGT),TGC(cookie)是该session的key,server把TGT和生成的ST发给浏览器。
- 浏览器重新请求该业务系统,同时url上带上了ST=xxx访问业务系统。
- 业务系统拿到ST后,向Server发起校验,校验成功后生成session和cookie,将cookie发送给浏览器。
- 浏览器带上该cookie,不带ST向业务系统发出请求。
- 业务系统验证cookie成功,系统登录成功。
参考链接:
CAS - CAS Protocol (apereo.github.io)
2021-08-17
消息响应
#
101 Switching Protocol
表示正在切换协议。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
成功响应
#
200 OK
请求成功。
201 CREATED
请求已成功,通常是POST、PUT请求后返回的响应。
重定向
#
301 MOVED PERMENENTLY
请求的资源已经被永久移动到新位置。
302 FOUND
重定向是临时的。
304 Not Modified
当文档内容没有修改,服务器会返回这个状态码,304响应禁止包含消息体。
客户端响应
#
400 BAD REQUEST
请求参数有误。
401 UNAUTHORIZED
当前请求需要用户验证。
403 FORBIDDEN
服务器已经理解请求,但是拒绝执行。
404 NOT FOUND
请求资源未找到。
405 Method Not Allowed
请求方法不能被用于请求相应的资源。该响应必须返回一个Allow头用以表述当前资源能够接受的请求方法的列表。
414 URI Too Long
请求的URI长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。通常是因为超过了GET方法传输数据的上限,可以改为POST方法。
服务端响应
#
500 INTERNAL SERVER ERROR
服务器内部错误。
502 BAD GATEWAY
服务器作为网关需要得到处理该请求的响应,但得到了一个错误的响应。
503 SERVICE UNAVILABLE
服务器没有准备好处理请求。
参考链接:
HTTP 响应代码 - HTTP | MDN (mozilla.org)
2021-08-13
- 支持string、list、set、有序set、hash等数据类型
- 通过
./redis-server [redis.conf]
启动服务。
- 通过
./redis-cli [-h hostname] [-p port]
连接redis,登录后通过AUTH password
来输入密码。
命令
#
keys *
查看当前库中的所有key。
exists key
判断某个key是否存在
rename key newkey
键重命名
- type key 查看key是什么类型
del key
删除指定的key数据
expire key 10
给key设定10秒的过期时间
ttl key
查看还有多少秒过期,-1表示永不过期,-2表示已过期
- select index 切换数据库,默认有16个库
- dbsize 查看当前库key的数量
set key value
设置字符串类型的键值对
get key
获取值
数据类型
#
string
#
set key value
设置值
get key
获取key对应的值
strlen key
获取值的长度。
- mset key1 value1 key2 value2 同时设置多个键值对。
- mget key1 key2 同时获取多个键值对。
- append key value 将给定的value追加到原值的末尾。
- setnx key value 只有当key不存在的时候才设置key的值。
- incr key key的值加一。
- decr key key的值减一。
- incrby key 步长 key的值加步长。
- decrby key 步长 key的值减步长。
- msetnx key1 value1 key2 value2 同时设置多个键值对,当有一个key存在的时候,所有的设置都会失败。
setex key seconds value
设置键值对的同时设置过期时间,单位是秒。
- String内部采用类似arraylist的机制,字符串实际分配的空间一般高于字符串的长度,当字符串长度小于1M时,扩容都是加倍的,超过1M时,每次扩容都是只增加1M。最大为512M。
链表
#
节点的结构
#
//adlist.h/listNode
//结构
typedef struct listNode {
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}
- 双端链表,获取节点的前置节点和后置节点的复杂度都是O(1)。
- 无环链表,表头指针的prev和表尾指针的next都是指向NULL。
- list结构的head指针和tail指针能快速获取表头结点和表尾节点,复杂度是O(1)。
- 可以通过list结构的len属性来获取链表中节点的数量,复杂度是O(1)。
命令
#
lpush/rpush k1 v1 v2 v3
从左/右边插入
lpop/rpop k1
从左/又边吐出一个值
lindex key index
按照索引下标获取元素
len key
获得列表的长度
lset key index value
将key的下标为index设置为value
lrange key start stop
按照下标索引获得元素,0表示左边第一个,-1表示右边第一个。
lrem key n value
删除n个value
hash
#
命令
#
hset key field value
设置值
hget key field
获取值
hdel key field[field...]
删除一个或多个键值对
hlen key
计算field的个数
hmget key field [field...]
批量获取
hmset key field value [field value ...]
批量设置
hexists key field
判断field是否存在
hkeys key
获取所有field
hvals key
获取所有value
hstrlen key field
获取value字符串长度