新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
小编这次要给大家分享的是Java如何实现令牌Token登录与退出,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。
成都创新互联服务项目包括银海网站建设、银海网站制作、银海网页制作以及银海网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,银海网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到银海省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
Token
之前的博客已经介绍了各种登录的方式,现在直接介绍一种现在比较流行的登录方式,无状态登录,只需要客户端携带令牌就能登陆,服务器不再存储登录状态。突然粉丝量爆棚,开心死了,所以抓紧写一篇硬核代码,分享给大家,拿来即用的代码,直接copy即可。
使用之前需要配置一下xml
com.auth0 java-jwt 3.4.0
下面为Java代码
package com.caeser.midrug.util; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.time.DateUtils; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.google.common.collect.Maps; public class JwtHelper { private static final String SECRET = "secret"; private static final String ISSURE= "caeser"; public static String getToken(Mapclaims) { Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTCreator.Builder builder= JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addMinutes(new Date(), 3)); claims.forEach((k,v) ->builder.withClaim(k, v)); return builder.sign(algorithm).toString(); } public static String getTokenByMinute(Map claims,int minute) { Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTCreator.Builder builder= JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addMinutes(new Date(), minute)); claims.forEach((k,v) ->builder.withClaim(k, v)); return builder.sign(algorithm).toString(); } public static String getTokenByHour(Map claims,int hour) { Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTCreator.Builder builder= JWT.create().withIssuer(ISSURE).withExpiresAt(DateUtils.addHours(new Date(), hour)); claims.forEach((k,v) ->builder.withClaim(k, v)); return builder.sign(algorithm).toString(); } public static Map verifyToken(String token){ Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSURE).build(); DecodedJWT jwt =verifier.verify(token); Map map = jwt.getClaims(); Map resultMap = Maps.newHashMap(); map.forEach((k,v)->resultMap.put(k,v.asString())); return resultMap; } public static void main(String[] args) { } }
解释
这段代码其实非常简单,作为调包侠的我们,只需要如何设置这个token生成就行了,我自己封装了一个按分钟和按小时校验过期的方法。当获取到登录名密码后,我们校验通过,就可以对该用户生成一个token然后返回给前端就行了。
package com.caeser.midrug.service.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.caeser.midrug.dao.UserAuthDao; import com.caeser.midrug.dto.Meta; import com.caeser.midrug.dto.UserAuthExe; import com.caeser.midrug.entity.UserAuth; import com.caeser.midrug.enums.UserAuthEnum; import com.caeser.midrug.service.UserAuthService; import com.caeser.midrug.util.JwtHelper; import com.caeser.midrug.util.MD5; import com.caeser.midrug.util.StaticVariable; @Service public class UserAuthServiceImpl implements UserAuthService{ @Autowired UserAuthDao userAuthDao; @Override public UserAuthExe getAuth(String account,String password) { UserAuthExe userAuthExe=new UserAuthExe(); Meta meta=new Meta(); // 将传过来的密码进行MD5加密 String inputPwd=MD5.getMd5(password); // 将账号与数据库内匹配 UserAuth dbAuth=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=new HashMap (); // 存储账号密码 claim.put("account", account); claim.put("password", password); // 账号密码保存到token String token=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); return userAuthExe; } }
其中有一串代码需要大家注意,虽然我的注释很全了,但是也要分清重点。
String token=JwtHelper.getTokenByMinute(claim, StaticVariable.LOGINTIME_MINUTE); // 将token存储到返回结果 userAuthExe.setToken(token);
就是生成并返回给前端的部分。我们再来看前端是如何保存的,我前端使用的Vue框架来写的。
async loginAction() { // 输入判空 if (this.loginAcStr === '' || this.loginPsStr === '') { return this.$message.error('请输入密码') } var qs = require('qs') const {data: res} = await axios.post(this.glAPI + '/home/login', qs.stringify({ username: this.loginAcStr, password: this.loginPsStr })) var dt = res.result if (dt.meta.status !== 1000) { if (dt.meta.status === 1001) { return this.$message.error('账号不存在') } else { return this.$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登录与退出的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。