Java令牌Token登錄與退出的實(shí)現(xiàn)
Token
之前的博客已經(jīng)介紹了各種登錄的方式,現(xiàn)在直接介紹一種現(xiàn)在比較流行的登錄方式,無狀態(tài)登錄,只需要客戶端攜帶令牌就能登陸,服務(wù)器不再存儲(chǔ)登錄狀態(tài)。突然粉絲量爆棚,開心死了,所以抓緊寫一篇硬核代碼,分享給大家,拿來即用的代碼,直接copy即可。
使用之前需要配置一下xml
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --><dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version></dependency>
下面為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(Map<String, String> claims) { 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<String, String> 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<String, String> 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<String, String> verifyToken(String token){ Algorithm algorithm = Algorithm.HMAC256(SECRET); JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSURE).build(); DecodedJWT jwt =verifier.verify(token); Map<String, Claim> map = jwt.getClaims(); Map<String, String> resultMap = Maps.newHashMap(); map.forEach((k,v)->resultMap.put(k,v.asString())); return resultMap; } public static void main(String[] args) { }}
解釋
這段代碼其實(shí)非常簡(jiǎn)單,作為調(diào)包俠的我們,只需要如何設(shè)置這個(gè)token生成就行了,我自己封裝了一個(gè)按分鐘和按小時(shí)校驗(yàn)過期的方法。當(dāng)獲取到登錄名密碼后,我們校驗(yàn)通過,就可以對(duì)該用戶生成一個(gè)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;@Servicepublic class UserAuthServiceImpl implements UserAuthService{ @Autowired UserAuthDao userAuthDao; @Override public UserAuthExe getAuth(String account,String password) { UserAuthExe userAuthExe=new UserAuthExe(); Meta meta=new Meta(); // 將傳過來的密碼進(jìn)行MD5加密 String inputPwd=MD5.getMd5(password); // 將賬號(hào)與數(shù)據(jù)庫(kù)內(nèi)匹配 UserAuth dbAuth=userAuthDao.getPwdByAccount(account); if(dbAuth==null) { // 如果賬號(hào)不存在 meta.setMsg(UserAuthEnum.ACCOUNT_NONE.getStateInfo()); meta.setStatus(UserAuthEnum.ACCOUNT_NONE.getState()); } if(dbAuth!=null) { // 賬號(hào)存在 // 判斷密碼是否正確 if(dbAuth.getPassword().equals(inputPwd)) { // 密碼正確 Map<String, String> claim=new HashMap<String, String>(); // 存儲(chǔ)賬號(hào)密碼 claim.put('account', account); claim.put('password', password); // 賬號(hào)密碼保存到token String token=JwtHelper.getTokenByMinute(claim, StaticVariable.LOGINTIME_MINUTE); // 將token存儲(chǔ)到返回結(jié)果 userAuthExe.setToken(token); // 將用戶信息保存到返回結(jié)果 // 返回賬號(hào) userAuthExe.setAcccount(account); // 返回用戶名 userAuthExe.setUserName(dbAuth.getUserName()); // 返回驗(yàn)證成功信息 meta.setMsg(UserAuthEnum.SUCCESS.getStateInfo()); meta.setStatus(UserAuthEnum.SUCCESS.getState()); }else { // 密碼錯(cuò)誤 meta.setMsg(UserAuthEnum.PWD_ERROR.getStateInfo()); meta.setStatus(UserAuthEnum.PWD_ERROR.getState()); } } // 存貯返回狀態(tài) userAuthExe.setMeta(meta); return userAuthExe; }}
其中有一串代碼需要大家注意,雖然我的注釋很全了,但是也要分清重點(diǎn)。
String token=JwtHelper.getTokenByMinute(claim, StaticVariable.LOGINTIME_MINUTE);// 將token存儲(chǔ)到返回結(jié)果userAuthExe.setToken(token);
就是生成并返回給前端的部分。我們?cè)賮砜辞岸耸侨绾伪4娴?,我前端使用的Vue框架來寫的。
async loginAction() { // 輸入判空 if (this.loginAcStr === ’’ || this.loginPsStr === ’’) { return this.$message.error(’請(qǐng)輸入密碼’) } 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(’賬號(hào)不存在’) } else { return this.$message.error(’賬號(hào)或密碼錯(cuò)誤’) } } // 密碼正確 this.$toast(’登陸成功’) // 調(diào)用父組件方法獲取登錄信息 this.$emit(’loginGetUserIcon’) // 保存token window.sessionStorage.setItem(’token’, dt.token) // 隱藏 this.loginDrawerVisible = false // 調(diào)用父組件方法刷新購(gòu)物車 this.$emit(’loginRefreshCart’) }
上述代碼里window.sessionStorage.setItem(’token’, dt.token)這句就是保存token,那么同理注銷也是針對(duì)sessionStoragewindow.sessionStorage.clear(),怎么樣是不是很簡(jiǎn)單呀!
分析
為了讓尋找代碼的小伙伴看到最有用的內(nèi)容,上面減少了很多廢話,直接上代碼上注釋就好,下面的分析可以理解為一段可能多余的話,在以往存儲(chǔ)session或者cookie的時(shí)候,可以理解為一個(gè)所有瀏覽器都通用的全局變量,而token就是去除這個(gè)全局變量的,將信息保存在了客戶端本地,減輕服務(wù)器壓力,網(wǎng)上各種討論哪個(gè)好哪個(gè)有優(yōu)勢(shì)哪個(gè)有缺點(diǎn),說真的,我還沒有見到實(shí)際的業(yè)務(wù)需求,所有并沒有那么深刻的體會(huì),也無法給出詳細(xì)的解答,就目前而言,我實(shí)現(xiàn)了無狀態(tài)的登錄,而且可以校驗(yàn)時(shí)間是否過期,這就夠了!
總結(jié)
就是如何生成一串字符串,如何保存,然后如何從這段字符串里分析出時(shí)間,然后判定是否過期,然后判定是否有效,就是這樣一個(gè)過程,我相信你可能或許不是很理解這個(gè)流程,但是你可以先嘗試著使用Token,我一開始是覺得很神奇的,后來想想,其實(shí)就是我們參加某次聚會(huì),別人給你發(fā)了個(gè)工作證明,你憑這個(gè)證明就能參加會(huì)議了,只不過放到網(wǎng)絡(luò)上面確實(shí)比較抽象。
到此這篇關(guān)于Java令牌Token登錄與退出的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java Token登錄與退出內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. ajax請(qǐng)求后臺(tái)得到j(luò)son數(shù)據(jù)后動(dòng)態(tài)生成樹形下拉框的方法2. 如何通過vscode運(yùn)行調(diào)試javascript代碼3. HTML <!DOCTYPE> 標(biāo)簽4. JS數(shù)據(jù)類型判斷的幾種常用方法5. 用Python自動(dòng)下載網(wǎng)站所有文件6. WML語(yǔ)言的基本情況7. python中str內(nèi)置函數(shù)用法總結(jié)8. Ajax實(shí)現(xiàn)頁(yè)面無刷新留言效果9. JSP+Servlet實(shí)現(xiàn)文件上傳到服務(wù)器功能10. python爬蟲使用requests發(fā)送post請(qǐng)求示例詳解
