jwt认证机制优势和原理_cookie、session、jwt

cookie、session、jwt都是用于HTTP用户认证的方式,最近在使用所以再次熟悉一下

Why?

HTTP是无状态的,无法获知用户的身份,所以就需要有一种手段可以实现能获知每个HTTP请求发起的用户是谁,还要能区分每个不同的用户。

Cookie

Cookie是保存用户信息的一种最简单的方式,cookie中可以保存用户的一些信息,存放在浏览器的本地存储中,并随着每次请求发送到服务器。

  1. 用户首次认证并登陆服务后,服务返回给用户的HTTP中带着一个服务器生成的cookie信息,浏览器会自动保存到本地,带用户下次再访问该网站时会自动带上该cookie;
  2. 不同的网站会发送不同的cookie,cookie和域名绑定,并能指定path;
  3. cookie有超时机制,如果超时需要重新认证再让服务方重新分配一个cookie;
  4. cookie可以指定secure=true属性,指定后只有https才能使用该cookie;
  5. cookei还可以指定httponly=true属性,可以防止js拿到cookie,只有服务器可以操作cookie

不足:

  1. 最大的原因是因为它存储在浏览器端,一些别有用心的人能够通过浏览器截获cookie(脚本、利用工具抓取等);
  2. Cookie在网络中很容易被劫持,这个问题需要用https解决;
  3. Cookie的失效时间是不受服务端控制的,用户可以修改;
  4. 同一站点能设置的cookie有限。

Session

Session是比cookie安全高的另一种会话保持技术,Session把信息存储的服务器端,在浏览器端只需要存储一个session id,服务端通过用户请求中带的session id自动获取用户信息。

session id虽然存储在cookie中,但所有用户信息都存放在服务端,通常公司对自己的用户信息都有更强的安全保护;

服务端可以存储用户大量信息,用户可以用一次登录就可以免密登录同一个公司的不同服务和网站;

session id通常会使用HMAC生成,并结合cookie使用,较为灵活,兼容性较好,防止篡改。

不足:

  1. 服务端存储session id需要承受更高的计算成本;
  2. 负载均衡需要考虑共享session机制;
  3. 查询session id是个查库操作,用户很多时会有性能问题;
  4. 无法跨域。

jwt

jwt是基于token验证机制的一种,目前受大多数网站和框架支持。jwt的原理是用户认证后发一个jwt token给用户,其中包含用户的信息,用户后续请求带上这个jwt,服务端就可以自动解析出用户信息。

jwt有三部分组成,都使用json格式:

Header
Payload
Signature

其中Header通常是:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload保存用户信息,比较随意,但通常是用户不铭感的信息:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature是根据jwt签名算法+服务端自定义的秘钥生成的hash信息:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

注意,header和payload部分都没有加密,所以不要存放铭感信息。

最后把三部分放在一起并使用BASE64_URL转义得到:

87ea1909f57b6192f158e9236a65ef09.png

golang版本实现如下:

1. header:结构固定,json.Mashal后再encode64
2. playload:和header一样,先json.Mashal后再base64UrlEncode
```
// Generate the signing string.  This is the
// most expensive part of the whole deal.  Unless you
// need this for something special, just go straight for
// the SignedString.
func (t *Token) SigningString() (string, error) {
	var err error
	parts := make([]string, 2)
	for i, _ := range parts {
		var jsonValue []byte
		if i == 0 {
			if jsonValue, err = json.Marshal(t.Header); err != nil {
				return "", err
			}
		} else {
			if jsonValue, err = json.Marshal(t.Claims); err != nil {
				return "", err
			}
		}

		parts[i] = EncodeSegment(jsonValue)
	}
	return strings.Join(parts, "."), nil
}
```
3. Signature:hash(playload,key)
```
// Implements the Sign method from SigningMethod for this signing method.
// Key must be []byte
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
	if keyBytes, ok := key.([]byte); ok {
		if !m.Hash.Available() {
			return "", ErrHashUnavailable
		}

		hasher := hmac.New(m.Hash.New, keyBytes)
		hasher.Write([]byte(signingString))

		return EncodeSegment(hasher.Sum(nil)), nil
	}

	return "", ErrInvalidKeyType
}
```
4. 最后,以上三部分join by .

jwt可以存放在cookie或者header中,推荐的做法是放到header,可以实现跨域:

Authorization: Bearer <token>

jwt解决了跨域、降低了服务端session开销问题,为分布式服务扫清了障碍,但也无法解决劫持问题,需要配合https才能实现更高的安全性。

引用:

https://jwt.io/introduction/​jwt.io https://github.com/dgrijalva/jwt-go​github.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值