JAVA中的Token 基于Token的身份验证实例
最近在做项目开始,涉及到服务器与安卓之间的接口开发,在此开发过程中发现了安卓与一般浏览器不同,安卓在每次发送请求的时候并不会带上上一次请求的SessionId,导致服务器每次接收安卓发送的请求访问时都新建一个Session进行处理,无法通过传统的绑定Session来进行保持登录状态和通讯状态。
基于传统方法无法判断安卓的每次请求访问状态,故查询资料了解到Token,特殊的身份证验证。以下是网上搜寻资料所得,作为学习总结资料。
令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作,下文我们就来详细的介绍一下关于基于Token的身份验证的教程
最近了解下基于Token的身份验证,跟大伙分享下。很多大型网站也都在用,比如Facebook,Twitter,Google+,Github等等,比起传统的身份验证方法,Token扩展性更强,也更安全点,非常适合用在Web应用或者移动应用上。Token的中文有人翻译成“令牌”,我觉得挺好,意思就是,你拿着这个令牌,才能过一些关卡。
传统身份验证的方法
HTTP是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。
解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的ID号发送给客户端,客户端收到以后把这个ID号存储在Cookie里,下次这个用户再向服务端发送请求的时候,可以带着这个Cookie,这样服务端会验证一个这个Cookie里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。Cookie里面存的是sessionID是session记录的id.
上面说的就是Session,我们需要在服务端存储为登录的用户生成的Session,这些Session可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的Session。
基于Token的身份验证方法
使用基于Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个Token,再把这个Token发送给客户端
客户端收到Token以后可以把它存储起来,比如放在Cookie里或者LocalStorage里
客户端每次向服务端请求资源的时候需要带着服务端签发的Token
服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据
JWT
实施Token验证的方法挺多的,还有一些标准方法,比如JWT,读作:jot,表示:JSONWebTokens。JWT标准的Token有三个部分:
header
payload
signature
中间用点分隔开,并且都会使用Base64编码,所以真正的Token看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
Header
header部分主要是两部分内容,一个是Token的类型,另一个是使用的算法,比如下面类型就是JWT,使用的算法是HS256。
{ "typ":"JWT", "alg":"HS256" }
上面的内容要用Base64的形式编码一下,所以就变成这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
Payload里面是Token的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。
下面是标准字段:
iss:Issuer,发行者sub:Subject,主题aud:Audience,观众exp:Expirationtime,过期时间nbf:Notbeforeiat:Issuedat,发行时间jti:JWTID
比如下面这个Payload,用到了iss发行人,还有exp过期时间。另外还有两个自定义的字段,一个是name,还有一个是admin。
{ "iss":"ninghao.net", "exp":"1438955445", "name":"wanghao", "admin":true }
使用Base64编码以后就变成了这个样子:
eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
Signature
JWT的最后一部分是Signature,这部分内容有三个部分,先是用Base64编码的header.payload,再用加密算法加密一下,加密的时候要放进去一个Secret,这个相当于是一个密码,这个密码秘密地存储在服务端。
header
payload
secret
varencodedString=base64UrlEncode(header)+"."+base64UrlEncode(payload);
HMACSHA256(encodedString,'secret');
处理完成以后看起来像这样:
SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
最后这个在服务端生成并且要发送给客户端的Token看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
客户端收到这个Token以后把它存储下来,下回向服务端发送请求的时候就带着这个Token。服务端收到这个Token,然后进行验证,通过以后就会返回给客户端想要的资源。
补充知识:JAVA后端生成Token(令牌),用于校验客户端
1.概述:
在web项目中,服务端和前端经常需要交互数据,有的时候由于网络相应慢,客户端在提交某些敏感数据(比如按照正常的业务逻辑,此份数据只能保存一份)时,如果前端多次点击提交按钮会导致提交多份数据,这种情况我们是要防止发生的。
2.解决方法:
①前端处理:在提交之后通过js立即将按钮隐藏或者置为不可用。
②后端处理:对于每次提交到后台的数据必须校验,也就是通过前端携带的令牌(一串唯一字符串)与后端校验来判断当前数据是否有效。
3.总结:
第一种方法相对来说比较简单,但是安全系数不高,第二种方法从根本上解决了问题,所以我推荐第二种方法
** *生成Token的工具类: */ packagered.hearing.eval.modules.token; importjava.security.MessageDigest; importjava.security.NoSuchAlgorithmException; importjava.util.Random; importsun.misc.BASE64Encoder; /** *生成Token的工具类 *@authorzhous *@since2018-2-2313:59:27 * */ publicclassTokenProccessor{ privateTokenProccessor(){}; privatestaticfinalTokenProccessorinstance=newTokenProccessor(); publicstaticTokenProccessorgetInstance(){ returninstance; } /** *生成Token *@return */ publicStringmakeToken(){ Stringtoken=(System.currentTimeMillis()+newRandom().nextInt(999999999))+""; try{ MessageDigestmd=MessageDigest.getInstance("md5"); bytemd5[]=md.digest(token.getBytes()); BASE64Encoderencoder=newBASE64Encoder(); returnencoder.encode(md5); }catch(NoSuchAlgorithmExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnnull; } }
/** * */ packagered.hearing.eval.modules.token; importjavax.servlet.http.HttpServletRequest; importorg.apache.commons.lang3.StringUtils; /** *Token的工具类 *@authorzhous *@since2018-2-2314:01:41 * */ publicclassTokenTools{ /** *生成token放入session *@paramrequest *@paramtokenServerkey */ publicstaticvoidcreateToken(HttpServletRequestrequest,StringtokenServerkey){ Stringtoken=TokenProccessor.getInstance().makeToken(); request.getSession().setAttribute(tokenServerkey,token); } /** *移除token *@paramrequest *@paramtokenServerkey */ publicstaticvoidremoveToken(HttpServletRequestrequest,StringtokenServerkey){ request.getSession().removeAttribute(tokenServerkey); } /** *判断请求参数中的token是否和session中一致 *@paramrequest *@paramtokenClientkey *@paramtokenServerkey *@return */ publicstaticbooleanjudgeTokenIsEqual(HttpServletRequestrequest,StringtokenClientkey,StringtokenServerkey){ Stringtoken_client=request.getParameter(tokenClientkey); if(StringUtils.isEmpty(token_client)){ returnfalse; } Stringtoken_server=(String)request.getSession().getAttribute(tokenServerkey); if(StringUtils.isEmpty(token_server)){ returnfalse; } if(!token_server.equals(token_client)){ returnfalse; } returntrue; } }
以上这篇JAVA中的Token基于Token的身份验证实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。