token编码过程:
第一部分:
json转化成字符串,然后做:base64url加密(JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "HS256", ##加密算法,哈希256是不能反解的
"typ": "JWT" ##token类型
}
第二部分:
json转化成字符串,然后做:base64url加密(本质是:base64加密+特定符号替换)
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
除了官方字段,你还可以在这个部分定义私有字段
PAYLOAD:DATA
{
自定义值: 可以是其他信息(不要放重要信息,base64url()是可以反解的)
"sub": "1234567890", ##主题
"name": "John Doe", ##私有字段
"iat": 1516239022 ##签发时间
}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
第三部分:
把第一,二部分的密文通过"."连接,然后进行HS256加密+盐,如果选择secret base64 encoded的话会给整体再用base64加密
VERIFY SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret ##密钥即盐值
) secret base64 encoded
cThIIoDvwdueQB468K5xDc5633seEFoqwxjF_xSJyQQ
然后把这三部分通过"."连接返回给用户
用户token认证
用户访问时会携带token,后端对token进行校验:
第一步:获取用户传进来的token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.cThIIoDvwdueQB468K5xDc5633seEFoqwxjF_xSJyQQ
第二步:通过"."切割出三部分,然后取出第二部分payload用户信息,并检查是否超时
PAYLOAD:DATA
{
自定义值: 可以是其他信息(不要放重要信息,base64url()是可以反解的)
"sub": "1234567890", ##id
"name": "John Doe", ##name
"iat": 1516239022 ##exp:超时时间
}
第三步:验证token值是否正确:
通过验证用户带的HS256密文和服务端通过用户传入token的第一二部分生成的HS256密文做对比
(1)密文:把第三部分的字符串,解密成返回给用户时的HS256的密文
(2)把第一,二部分的密文通过"."连接,然后进行HS256加密+盐
然后比较(1),(2)
可能出现的安全隐患:
1.用户修改了第二部分密文的超时时间的话,验证token的时候,服务端生成的第三部分密文会和用户带的第三部分密文不同
2.用户同时修改了第一和第二部分的,和第三部分的密文的话:此时就体现出进行HS256加密的同时加盐的重要性。因为服务端生成第三部分的密文时会加上盐值。
3.这个盐值很重要的。