# OAuth认证

  • OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。
  • 每个令牌授权对应一个特定的网站(如视频网站)在特定时间内(如2小时内)访问特定的资源。
  • 这样OAuth让用户可以授权第三方网站访问她, 存储在另外服务提供者的某些特定信息,而非所有内容。

例:微信网页授权就是授权码模式的OAuth授权模式:
1.用户登录某个视频网站
2.视频网站提供一个微信授权页面
3.用户同意授权,视频网站服务器重定向到之前设置好的redirect_url(服务器地址),并附带上授权码(code)
4.视频网站服务器用上一步获取到的code去向微信授权服务器发送请求,获取access_token,即令牌
5.视频网站服务器拿到access_token后去请求微信授权服务器获取用户基本信息,如头像、昵称等

  • 用户输入用户名、密码或用短信验证码方式登录系统
  • 服务器验证后,创建一个session信息,并且生成sessionId存到cookie,发送回浏览器
  • 下次客户端再请求,自动带上cookie信息,服务器通过cookie获取sessionId进行session信息校验

缺点:
1.只能用于web,不能用于app
2.使用cookie需要考虑跨域问题
3.cookie存在CSRF(跨站请求伪造)风险
4.session存在服务器,需要考虑服务器的负担以及同步问题

CSRF(跨站请求伪造):盗用cookie信息,以你的名义发送恶意请求

  • 验证HTTP Referer字段,它记录了http请求的来源地址
  • 请求地址中添加token验证
  • 在http头中自定义属性并验证

# 基于JWT的Token认证

  • 用户输入密码或者短信验证登录系统
  • 服务端验证,将认证信息通过指定算法进行加密,将加密结果发送给客户端,加密的字符串即是JWT
  • 客户端拿到token存储到本地LocalStorage或本地数据库
  • 下次客户端再请求,将token附加在http请求的header中
  • 服务器获取到header中的token,通过相同算法对token中的用户名以及其他信息进行加密验证,如果验证结果相同, 则说明这个请求是正常的,未经过篡改

优点:
1.使用json作为数据传输,有广泛的通用性,并且体积小,便于传输
2.不需要服务端保存任何信息
3.JWT可以存储业务相关信息,如:用户名、角色等等

JWT组成: header.payload.signature

  • header
{
  "alg": "HS256", // 该字段指定生成signature的算法,默认值为 HS256
  "typ": "jwt"    // 默认值为 jwt 
}

生成的base64UrlEncode编码为: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

  • payload
{
    "iss": "admin",           //该JWT的签发者
    "iat": 1535967430,        //签发时间
    "exp": 1535974630,        //过期时间
    "nbf": 1535967430,        //该时间之前不接收处理该Token
    "sub": "www.admin.com",   //面向的用户
    "jti": "9f10e796726e332cec401c569969e13e"   //该Token唯一标识
}

生成的base64UrlEncode编码为: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

  • signature
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  123456
)

这个操作是对header和payload机械能baseUrlEncode编码后进行拼接,通过key(这里是123456)进行HS256算法签名

得到的签名的base64UrlEncode编码为: keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

也被称为签名哈希:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

key是什么

key是只保存与服务端的secret,不可被用户知晓

以上三个部分用'.'来拼接起来得到的字符串,就是整个JWT