转载请注明出处:基于Token的登陆验证模式 https://blog.csdn.net/llf919329450/article/details/83389234
在讨论基于Token的登陆验证模式之前,我们先来了解一下基于cookie-session的验证模式:
什么是基于cookie-session的验证模式?Cookie是网站储存在用户浏览器本地,用于对用户状态信息及用户身份进行辨别的一组数据,而session则是对应储存在服务器的一组数据。当用户进行登录时,首先由服务器接受用户的登陆参数(如用户名,密码等),然后在服务器端建立对应用户的session,用于保存该用户的登陆状态,再由服务端告诉浏览器该存储的cookie信息,经过这样的步骤之后,浏览器的cookie就成了服务器检验用户是否合法登陆的唯一令牌。用户的每一次操作,都会由浏览器提交cookie,再交由服务器来检验该cookie是否合法,以此决定是否放行这条请求。
基于cookie-session的验证模式有哪些优点,又有哪些缺点?优点是基于cookie-session的验证模式可以减少请求时提交参数的工作量,但是也因此带来了某些隐患,在浏览器使用GET请求访问页面时,默认会带上该域名下的cookie,不法分子就可以利用这个跨站请求漏洞模拟用户登录,给用户带来经济损失。
再者,由于session是存储在服务器上的用户登录令牌,如果有很多个用户登录的话,服务器上的资源也就使用的越多。cookie最致命的一点,是由于cookie不需要黑客去破解,他只需要拿到cookie后原样提交到网站域名下,就可以模拟用户登录之后,执行各种请求了。
在这种背景下,一种全新的验证模式应运而生,那就是基于token的登录验证模式。
什么是基于Token的验证模式?Token是一种无状态、跨服务器、高性能的验证模式,它不同于Cookie-Session需要在同一个服务器上验证,即使是分布式服务器,它也表现的游刃有余,因为Session跟Cookie的验证必须在一个服务器上进行,而Token的验证在任何服务器上都可以进行。比起传统的Cookie-Session的验证方式,Token的验证方式更安全,扩展性更强,非常适用于WEB应用或移动应用。很多大型公司的验证方式都是使用Token,比如著名的开源社区GitHub。
Token验证方式的基本流程使用Token进行验证的时候,服务端不需要存储用户的登陆记录,请求过程大概是这样的:
客户端或Web页面使用用户名、密码请求登陆服务器验证用户名密码后,签发Token,并返回Token到客户端客户端收到Token后,将它存放起来(放在Local Storage或Http请求的Header中)客户端每次的请求都要携带服务端签发的Token用于验证服务端验证Token,如果合法就返回客户端请求的数据 如何签发一个合法的Token?首先,一个合法的Token由三个部分组成,即:Header(头部)、Payload(载荷),以及Signature(签名),完整的Token是一个字符串,形如A.B.C,其中:
A、即Header,通常是一个json字符串,其中包含两个字段:typ和alg,其中,typ标识该Token使用的标准,一般现在大多数都是使用JWT(Json Web Token)作为Token的验证标准,alg标识该Token生成签名(Signature)使用的加密算法,一般默认为HS256,由此可得,一般的Header格式如下:
{ "typ":"JWT", //标识该Token使用的验证标准 "alg":"HS256" //标识该Token的签名使用的加密方式 }将Header用Base64算法加密后,得到A:
JTdCJTIydHlwJTIyJTNBJTIySldUJTIyJTJDJTIwJTIyYWxnJTIyJTNBJTIySFMyNTYlMjIlN0Q=B、Payload,它也是一个Json字符串,里面存放着标识用户信息的字段或一些标准字段,这些标准字段有:
iss:Issuer,发行者sub:Subject,主题aud:Audience,观众exp:Expiration time,过期时间nbf:Not beforeiat:Issued at,发行时间jti:JWT ID除了这些标准字段以外,你还可以添加任何你想要添加的内容。比如下面这个Payload:
{ "iss":"Nirtonsoft", //该Token的发行者 "iat":"1540486585", //该Token的发布时间 "exp":"1543164883", //该Token的过期时间 "uid":"E548VTEYA762Q87W", //用户ID标识 "isAdmin":true //是否管理员 }将Payload经过Base64加密后,得到B:
JTdCJTIyaXNzJTIyJTNBJTIyTmlydG9uc29mdCUyMiUyQyUyMCUyMmlhdCUyMiUzQSUyMjE1NDA0ODY1ODUlMjIlMkMlMjAlMjJleHAlMjIlM0ElMjIxNTQzMTY0ODgzJTIyJTJDJTIwJTIydWlkJTIyJTNBJTIyRTU0OFZURVlBNzYyUTg3VyUyMiUyQyUyMCUyMmlzQWRtaW4lMjIlM0F0cnVlJTdEC、Signature,Signature需要由Header和Payload计算得出,首先,将前面加密得到的A和B用”.”连接起来:A + “.” + B,得到:
JTdCJTIydHlwJTIyJTNBJTIySldUJTIyJTJDJTIwJTIyYWxnJTIyJTNBJTIySFMyNTYlMjIlN0Q=.JTdCJTIyaXNzJTIyJTNBJTIyTmlydG9uc29mdCUyMiUyQyUyMCUyMmlhdCUyMiUzQSUyMjE1NDA0ODY1ODUlMjIlMkMlMjAlMjJleHAlMjIlM0ElMjIxNTQzMTY0ODgzJTIyJTJDJTIwJTIydWlkJTIyJTNBJTIyRTU0OFZURVlBNzYyUTg3VyUyMiUyQyUyMCUyMmlzQWRtaW4lMjIlM0F0cnVlJTdE将A.B经过A中alg指定的算法加密,由于HS256算法加密需要密钥,这里我们假定密钥为“Nirtonsoft”,加密后就得到Signature(即为C)为:
79ea71266c8cf1596186d2cdf9b61d5daa2c08bc289d4e08c430490a6bf678e5现在我们可以得到完整的Token(A.B.C)了:
JTdCJTIydHlwJTIyJTNBJTIySldUJTIyJTJDJTIwJTIyYWxnJTIyJTNBJTIySFMyNTYlMjIlN0Q=.JTdCJTIyaXNzJTIyJTNBJTIyTmlydG9uc29mdCUyMiUyQyUyMCUyMmlhdCUyMiUzQSUyMjE1NDA0ODY1ODUlMjIlMkMlMjAlMjJleHAlMjIlM0ElMjIxNTQzMTY0ODgzJTIyJTJDJTIwJTIydWlkJTIyJTNBJTIyRTU0OFZURVlBNzYyUTg3VyUyMiUyQyUyMCUyMmlzQWRtaW4lMjIlM0F0cnVlJTdE.79ea71266c8cf1596186d2cdf9b61d5daa2c08bc289d4e08c430490a6bf678e5 总结一下基于Token验证的优点 安全,传统基于Cookie-Session的验证方式,数据必须存在于Cookie中,而Cookie受CSRF(跨域请求)影响较大,故不是一种安全的做法,Token可以放置于Header中,相对而言较为安全。简单,很多原生的平台并不支持Cookie操作,例如IOS\Android,Token在这些平台上显得更加游刃有余,Cookie可能还得折腾一会呢。无状态,token 是无状态的,服务器端不需要保留任何信息,每个 token 都会包含所有需要的用户信息。服务器端可以只负责签发和解析 token,这样就减少了服务器资源的占用。可拓展,token可以携带一些较为私密的信息(通过更改签发Token的算法,比如RSA)这样就避免了频繁的数据库查询和验证。支持跨域请求,Cookie不可跨域,跨域就不会提交其他域名下的Cookie,token就不一样了,想交哪就交哪,想怎么交就怎么交。