十五、springboot集成jwt:0.11.1

一、gradle引入依赖

    // jjwt
    implementation 'io.jsonwebtoken:jjwt-api:0.11.1'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.1'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.1'

二、JwtTokenUtil.java工具

1、配置文件中添加

## JWT 密钥 - start
jwt:
  secret-key: 789qweq44878877qsdgrtqw848fg789qweq44878877qsfg)
  access-token-expire-time: PT2H
  refresh-token-expire-time: PT8H
  refresh-token-expire-app-time: P30D
  issuer: zz.com
## JWT 密钥 - end

创建映射类

@Configuration
@ConfigurationProperties(prefix = "jwt")
public class TokenSettings {

    private String secretKey;
    private Duration accessTokenExpireTime;
    private Duration refreshTokenExpireTime;
    private Duration refreshTokenExpireAppTime;
    private String  issuer;


    get/set。。。
}

 

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
/**
 * @ClassName : JwtTokenUtil.java
 * @Description : 描述
 * @Author : zhangz
 * @createTime 2020年07月27日 11:31:00
 */
public class JwtTokenUtil {

    private static final Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);

    private static String secretKey;
    private static Duration accessTokenExpireTime;
    private static Duration refreshTokenExpireTime;
    private static Duration refreshTokenExpireAppTime;
    private static String  issuer;

    public static void setTokenSettings(TokenSettings tokenSettings){
        secretKey=tokenSettings.getSecretKey();
        accessTokenExpireTime=tokenSettings.getAccessTokenExpireTime();
        refreshTokenExpireTime=tokenSettings.getRefreshTokenExpireTime();
        refreshTokenExpireAppTime=tokenSettings.getRefreshTokenExpireAppTime();
        issuer=tokenSettings.getIssuer();
    }

    /**
     * 生成 access_token
     * @return       java.lang.String
     */
    public static String getAccessToken(String subject, Map<String,Object> claims){
        return generateToken(issuer,subject,claims,accessTokenExpireTime.toMillis(),secretKey);
    }

    /**
     * 生产 App端 refresh_token
     * @return       java.lang.String
     */
    public static String getRefreshAppToken(String subject,Map<String,Object> claims){
        return generateToken(issuer,subject,claims,refreshTokenExpireAppTime.toMillis(),secretKey);
    }

    /**
     * 生产 PC refresh_token
     * @return       java.lang.String
     */
    public static String getRefreshToken(String subject,Map<String,Object> claims){
        return generateToken(issuer,subject,claims,refreshTokenExpireTime.toMillis(),secretKey);
    }

    /**
     * 签发token
     * @param issuer 签发人
     * @param subject 代表这个JWT的主体,即它的所有人 一般是用户id
     * @param claims 存储在JWT里面的信息 一般放些用户的权限/角色信息
     * @param ttlMillis 有效时间(毫秒)
     * @return       java.lang.String
     */
    public static String generateToken(String issuer, String subject,Map<String, Object> claims, long ttlMillis,String secret) {

//        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secret);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        JwtBuilder builder = Jwts.builder();
        if(null!=claims){
            builder.setClaims(claims);
        }
        if (!StringUtils.isEmpty(subject)) {
            builder.setSubject(subject);
        }
        if (!StringUtils.isEmpty(issuer)) {
            builder.setIssuer(issuer);
        }
        builder.setIssuedAt(now);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        builder.signWith(signingKey);
        return builder.compact();
    }

    /**
     * 获取用户id
     * @return       java.lang.String
     */
    public static String getUserId(String token){
        String userId=null;
        try {
            Claims claims = getClaimsFromToken(token);
            userId = claims.getSubject();
        } catch (Exception e) {
            log.error("eror={}",e);
        }
        return userId;
    }

    /**
     * 获取用户名
     * @return       java.lang.String
     */
    public static String getUserName(String token){

        String username=null;
        try {
            Claims claims = getClaimsFromToken(token);
            username = (String) claims .get(Constant.JWT_USER_NAME);
        } catch (Exception e) {
            log.error("eror={}",e);
        }
        return username;
    }

    /**
     * 获取用户电话
     * @return       java.lang.String
     */
    public static String getUserMobile(String token){

        String userMobile=null;
        try {
            Claims claims = getClaimsFromToken(token);
            userMobile = (String) claims .get(Constant.JWT_USER_MOBILE);
        } catch (Exception e) {
            log.error("eror={}",e);
        }
        return userMobile;
    }

    /**
     * 从令牌中获取数据声明
     * @return       io.jsonwebtoken.Claims
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(secretKey)).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    /**
     * 校验令牌
     * @return       java.lang.Boolean
     */
    public static Boolean validateToken(String token) {
        Claims claimsFromToken = getClaimsFromToken(token);
        return (null!=claimsFromToken && !isTokenExpired(token));
    }

    /**
     * 验证token 是否过期
     * @return       java.lang.Boolean
     */
    public static Boolean isTokenExpired(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            log.error("error={}",e);
            return true;
        }
    }

    /**
     * 刷新token
     * @return       java.lang.String
     */
    public static String refreshToken(String refreshToken,Map<String, Object> claims) {
        String refreshedToken;
        try {
            Claims parserclaims = getClaimsFromToken(refreshToken);
            /**
             * 刷新token的时候如果为空说明原先的 用户信息不变 所以就引用上个token里的内容
             */
            if(null==claims){
                claims=parserclaims;
            }
            refreshedToken = generateToken(parserclaims.getIssuer(),parserclaims.getSubject(),claims,accessTokenExpireTime.toMillis(),secretKey);
        } catch (Exception e) {
            refreshedToken = null;
            log.error("error={}",e);
        }
        return refreshedToken;
    }

    /**
     * 获取token的剩余过期时间
     * @return       long
     */
    public static long getRemainingTime(String token){
        long result=0;
        try {
            long nowMillis = System.currentTimeMillis();
            result= getClaimsFromToken(token).getExpiration().getTime()-nowMillis;
        } catch (Exception e) {
            log.error("error={}",e);
        }
        return result;
    }

三、登录时生成token

    @Override
    public Map<String, Object> login(User vo) {
        User user = userRepository.findByUserMobile(vo.getUserMobile()); // 数据库查询
        if (BeanUtil.isNotEmpty(user)) {
            if(!PasswordUtils.matches(user.getSalt(),vo.getUserPassword(),user.getUserPassword())){
                throw new BusinessException(BaseResponseCode.PASSWORD_ERROR); // 判断密码是否正确
            }
            Map<String,Object> claims=new HashMap<>();
            claims.put(Constant.JWT_USER_NAME,user.getUserRealName());
            claims.put(Constant.JWT_USER_MOBILE,user.getUserMobile());
            Map<String ,Object> map = new HashMap();
            String refresh_token=JwtTokenUtil.getRefreshToken(user.getUserId().toString(),claims);
            map.put("token", refresh_token);
            map.put("user",user);
            return map;
        }
        return null;
    }

四、携带token进行访问验证(登录成功将token返回到前端,前端将token添加到请求头"token"中),后台携带获取token,并获取userId,获取失败则token无效

        Result result = new Result();
		String token = request.getHeader("token");
		if(BeanUtil.isEmpty(token)){
			token = request.getParameter("token");
		}
		// String url = request.getRequestURL().toString();
		if (StringUtils.isNotBlank(token)) {
//			Claims claims = JwtTokenUtil.getClaimsFromToken(token); // 从令牌中获取数据声明
//			Long time = JwtTokenUtil.getRemainingTime(token); // 剩余过期时间
//			Boolean b = JwtTokenUtil.validateToken(token); // 校验token
			String id = JwtTokenUtil.getUserId(token); // 获取用户id
			String userMobile = JwtTokenUtil.getUserMobile(token); // 获取用户电话
			if (BeanUtil.isNotEmpty(id) && BeanUtil.isNotEmpty(userMobile)) {
				User user = userService.getOne(Integer.parseInt(id));
				if (BeanUtil.isNotEmpty(user) && user.getUserMobile().equals(userMobile)) {
					if (user.getUserOn().equals(EnumUtils.UserEnum.NORMAL.getValue())) {
						request.setAttribute(CommonUtil.SYSTEM_USER, user);
						// 刷新token有效期
						userTokenService.refresh(token);
					} else {
						result.setStatus(ResultCode.PARAM_ERROR);
						result.setMsg("用户账号未启用,登录失败");
					}
				} else {
					result.setStatus(ResultCode.PARAM_ERROR);
					result.setMsg("账号异常,请重新尝试");
				}
			} else {
				result.setStatus(ResultCode.PARAM_ERROR);
				result.setMsg("token失效,请重新登录");
			}
		}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值