Java令牌Token登录与退出

Java令牌Token登录与退出

在这里插入图片描述

Token

之前的博客已经介绍了各种登录的方式,现在直接介绍一种现在比较流行的登录方式,无状态登录,只需要客户端携带令牌就能登陆,服务器不再存储登录状态。突然粉丝量爆棚,开心死了,所以抓紧写一篇硬核代码,分享给大家,拿来即用的代码,直接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) {
		
	}
}

解释

这段代码其实非常简单,作为调包侠的我们,只需要如何设置这个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)) {
				// 密码正确
				Map<String, String> claim=new HashMap<String, String>();
				// 存储账号密码
				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,我一开始是觉得很神奇的,后来想想,其实就是我们参加某次聚会,别人给你发了个工作证明,你凭这个证明就能参加会议了,只不过放到网络上面确实比较抽象。

展开阅读全文
©️2020 CSDN 皮肤主题: 代码科技 设计师: Amelia_0503 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值