Java令牌Token登录与退出的实现
Token
之前的博客已经介绍了各种登录的方式,现在直接介绍一种现在比较流行的登录方式,无状态登录,只需要客户端携带令牌就能登陆,服务器不再存储登录状态。突然粉丝量爆棚,开心死了,所以抓紧写一篇硬核代码,分享给大家,拿来即用的代码,直接copy即可。
使用之前需要配置一下xml
com.auth0 java-jwt 3.4.0
下面为Java代码
packagecom.caeser.midrug.util; importjava.util.Date; importjava.util.HashMap; importjava.util.Map; importorg.apache.commons.lang3.time.DateUtils; importcom.auth0.jwt.JWT; importcom.auth0.jwt.JWTCreator; importcom.auth0.jwt.JWTVerifier; importcom.auth0.jwt.algorithms.Algorithm; importcom.auth0.jwt.interfaces.Claim; importcom.auth0.jwt.interfaces.DecodedJWT; importcom.google.common.collect.Maps; publicclassJwtHelper{ privatestaticfinalStringSECRET="secret"; privatestaticfinalStringISSURE="caeser"; publicstaticStringgetToken(Mapclaims){ Algorithmalgorithm=Algorithm.HMAC256(SECRET); JWTCreator.Builderbuilder=JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addMinutes(newDate(),3)); claims.forEach((k,v)->builder.withClaim(k,v)); returnbuilder.sign(algorithm).toString(); } publicstaticStringgetTokenByMinute(Map claims,intminute){ Algorithmalgorithm=Algorithm.HMAC256(SECRET); JWTCreator.Builderbuilder=JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addMinutes(newDate(),minute)); claims.forEach((k,v)->builder.withClaim(k,v)); returnbuilder.sign(algorithm).toString(); } publicstaticStringgetTokenByHour(Map claims,inthour){ Algorithmalgorithm=Algorithm.HMAC256(SECRET); JWTCreator.Builderbuilder=JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addHours(newDate(),hour)); claims.forEach((k,v)->builder.withClaim(k,v)); returnbuilder.sign(algorithm).toString(); } publicstaticMap verifyToken(Stringtoken){ Algorithmalgorithm=Algorithm.HMAC256(SECRET); JWTVerifierverifier=JWT.require(algorithm).withIssuer(ISSURE).build(); DecodedJWTjwt=verifier.verify(token); Map map=jwt.getClaims(); Map resultMap=Maps.newHashMap(); map.forEach((k,v)->resultMap.put(k,v.asString())); returnresultMap; } publicstaticvoidmain(String[]args){ } }
解释
这段代码其实非常简单,作为调包侠的我们,只需要如何设置这个token生成就行了,我自己封装了一个按分钟和按小时校验过期的方法。当获取到登录名密码后,我们校验通过,就可以对该用户生成一个token然后返回给前端就行了。
packagecom.caeser.midrug.service.impl; importjava.util.HashMap; importjava.util.List; importjava.util.Map; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Service; importcom.caeser.midrug.dao.UserAuthDao; importcom.caeser.midrug.dto.Meta; importcom.caeser.midrug.dto.UserAuthExe; importcom.caeser.midrug.entity.UserAuth; importcom.caeser.midrug.enums.UserAuthEnum; importcom.caeser.midrug.service.UserAuthService; importcom.caeser.midrug.util.JwtHelper; importcom.caeser.midrug.util.MD5; importcom.caeser.midrug.util.StaticVariable; @Service publicclassUserAuthServiceImplimplementsUserAuthService{ @Autowired UserAuthDaouserAuthDao; @Override publicUserAuthExegetAuth(Stringaccount,Stringpassword){ UserAuthExeuserAuthExe=newUserAuthExe(); Metameta=newMeta(); //将传过来的密码进行MD5加密 StringinputPwd=MD5.getMd5(password); //将账号与数据库内匹配 UserAuthdbAuth=userAuthDao.getPwdByAccount(account); if(dbAuth==null){ //如果账号不存在 meta.setMsg(UserAuthEnum.ACCOUNT_NONE.getStateInfo()); meta.setStatus(UserAuthEnum.ACCOUNT_NONE.getState()); } if(dbAuth!=null){ //账号存在 //判断密码是否正确 if(dbAuth.getPassword().equals(inputPwd)){ //密码正确 Mapclaim=newHashMap (); //存储账号密码 claim.put("account",account); claim.put("password",password); //账号密码保存到token Stringtoken=JwtHelper.getTokenByMinute(claim,StaticVariable.LOGINTIME_MINUTE); //将token存储到返回结果 userAuthExe.setToken(token); //将用户信息保存到返回结果 //返回账号 userAuthExe.setAcccount(account); //返回用户名 userAuthExe.setUserName(dbAuth.getUserName()); //返回验证成功信息 meta.setMsg(UserAuthEnum.SUCCESS.getStateInfo()); meta.setStatus(UserAuthEnum.SUCCESS.getState()); }else{ //密码错误 meta.setMsg(UserAuthEnum.PWD_ERROR.getStateInfo()); meta.setStatus(UserAuthEnum.PWD_ERROR.getState()); } } //存贮返回状态 userAuthExe.setMeta(meta); returnuserAuthExe; } }
其中有一串代码需要大家注意,虽然我的注释很全了,但是也要分清重点。
Stringtoken=JwtHelper.getTokenByMinute(claim,StaticVariable.LOGINTIME_MINUTE); //将token存储到返回结果 userAuthExe.setToken(token);
就是生成并返回给前端的部分。我们再来看前端是如何保存的,我前端使用的Vue框架来写的。
asyncloginAction(){ //输入判空 if(this.loginAcStr===''||this.loginPsStr===''){ returnthis.$message.error('请输入密码') } varqs=require('qs') const{data:res}=awaitaxios.post(this.glAPI+'/home/login',qs.stringify({ username:this.loginAcStr, password:this.loginPsStr })) vardt=res.result if(dt.meta.status!==1000){ if(dt.meta.status===1001){ returnthis.$message.error('账号不存在') }else{ returnthis.$message.error('账号或密码错误') } } //密码正确 this.$toast('登陆成功') //调用父组件方法获取登录信息 this.$emit('loginGetUserIcon') //保存token window.sessionStorage.setItem('token',dt.token) //隐藏 this.loginDrawerVisible=false //调用父组件方法刷新购物车 this.$emit('loginRefreshCart') }
上述代码里window.sessionStorage.setItem('token',dt.token)这句就是保存token,那么同理注销也是针对sessionStoragewindow.sessionStorage.clear(),怎么样是不是很简单呀!
分析
为了让寻找代码的小伙伴看到最有用的内容,上面减少了很多废话,直接上代码上注释就好,下面的分析可以理解为一段可能多余的话,在以往存储session或者cookie的时候,可以理解为一个所有浏览器都通用的全局变量,而token就是去除这个全局变量的,将信息保存在了客户端本地,减轻服务器压力,网上各种讨论哪个好哪个有优势哪个有缺点,说真的,我还没有见到实际的业务需求,所有并没有那么深刻的体会,也无法给出详细的解答,就目前而言,我实现了无状态的登录,而且可以校验时间是否过期,这就够了!
总结
就是如何生成一串字符串,如何保存,然后如何从这段字符串里分析出时间,然后判定是否过期,然后判定是否有效,就是这样一个过程,我相信你可能或许不是很理解这个流程,但是你可以先尝试着使用Token,我一开始是觉得很神奇的,后来想想,其实就是我们参加某次聚会,别人给你发了个工作证明,你凭这个证明就能参加会议了,只不过放到网络上面确实比较抽象。
到此这篇关于Java令牌Token登录与退出的实现的文章就介绍到这了,更多相关JavaToken登录与退出内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。