冒红不影响正常的运行,如想结果按照以下步骤。
pom.xml增加如下依赖:
<!--解决@ConfigurationProperties报红,引入此依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
代码如下:
package com.sccl.springbootjwt.jwt;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.JWTCreator.Builder;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.sccl.springbootjwt.bean.UserBean;
import com.sccl.springbootjwt.exception.customer.CustomerException;
import com.sccl.springbootjwt.exception.customer.TokenIllegalException;
import com.sccl.springbootjwt.exception.customer.TokenMisMatchException;
import com.sccl.springbootjwt.message.CodeEnum;
import com.sccl.springbootjwt.util.Object2MapUtil;
import com.sccl.springbootjwt.util.RedisProvide;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.google.common.base.Objects;
import javax.annotation.Resource;
import java.util.*;
/**
* Create by wangbin
* 2019-12-04-10:48
*/
@Data
@Component
@ConfigurationProperties(prefix = "com.sccl.springbootjwt")
public class JwtProvide {
@Resource
private RedisProvide redisProvide;
/**
* 功能描述 私钥
* 开发时间 2019-12-04-10:48
*/
private String secret;
/**
* 功能描述 发布者
* 开发时间 2019-12-04-10:48
*/
private String issuer;
/**
* 功能描述 主题
* 开发时间 2019-12-04-10:48
*/
private String subject;
/**
* 功能描述 签名的观众 也可以理解谁接受签名的
* 开发时间 2019-12-04-10:48
*/
private String audience;
/**
* 功能描述 自定义签名
* 开发时间 2019-12-04-10:48
*/
private Map<String, String> claims;
/**
* 功能描述 过期时间
* 开发时间 2019-12-04-10:48
*/
private Integer hour;
/**
* 功能描述 刷新时间
* 开发时间 2019-12-04-10:48
*/
private Integer minute;
/**
* 创建 默认xx小时后过期的 Token
* @param claims
* @return
*/
public String createToken(Map<String, Object> claims) {
return createToken(claims,hour,minute);
}
/**
* 创建 hour 小时后过期的 Token
*
* @param claims
* @param hour 有效时间
* @param minute 刷新时间
* @return
*/
public String createToken(Map<String, Object> claims, int hour, int minute) {
Payload createPayload = this.createPayload(hour, minute);
createPayload.setClaims(claims);
Algorithm hmac256 = Algorithm.HMAC256(this.getSecret());
return createToken(createPayload, hmac256);
}
/**
* 根据负载和算法创建 Token
*
* @param payload
* @param algorithm
* @return
*/
public String createToken(Payload payload, Algorithm algorithm) {
Builder headBuilder = createHeaderBuilder(algorithm);
Builder publicClaimbuilder = addPublicClaimBuilder(headBuilder, payload);
Builder privateClaimbuilder = addPrivateClaimbuilder(publicClaimbuilder, payload);
String token = privateClaimbuilder.sign(algorithm);
return token;
}
/**
* 创建自定小时后过期的负载
*
* @param hour 有效时间
* @param minute 刷新时间
* @return
*/
public Payload createPayload(int hour, int minute) {
Payload payload = new Payload();
payload.setIssuer(this.getIssuer());
payload.setSubject(this.getSubject());
payload.setAudiences(this.getAudience());
this.setIssuedAtAndExpiresAt(new Date(), hour, minute, payload);
return payload;
}
/**
* 添加私有声明
*
* @param builder
* @param payload
* @return
*/
private Builder addPrivateClaimbuilder(Builder builder, Payload payload) {
Map<String, Object> claims = payload.getClaims();
if (!CollectionUtils.isEmpty(claims)) {
claims.forEach((k, v) -> {
builder.withClaim(k, (String) v);
});
}
builder.withClaim("refreshAt", payload.getRefreshAt());
return builder;
}
/**
* 添加公共声明
*
* @param builder
* @param payload
* @return
*/
private Builder addPublicClaimBuilder(Builder builder, Payload payload) {
// 生成签名者
if (!StringUtils.isEmpty(payload.getIssuer())) {
builder.withIssuer(payload.getIssuer());
}
// 生成签名主题
if (!StringUtils.isEmpty(payload.getSubject())) {
builder.withSubject(payload.getSubject());
}
// 生成签名的时间
if (payload.getIssuedAt() != null) {
builder.withIssuedAt(payload.getIssuedAt());
}
// 签名过期的时间
if (payload.getExpiresAt() != null) {
builder.withExpiresAt(payload.getExpiresAt());
}
// 签名领取签名的观众 也可以理解谁接受签名的
if (CollectionUtils.isEmpty(payload.getAudience())) {
payload.getAudience().forEach((s) -> {
builder.withAudience(s);
});
}
return builder;
}
/**
* 创建 JWT 头部信息
*
* @param algorithm
* @return
*/
private Builder createHeaderBuilder(Algorithm algorithm) {
Builder builder = JWT.create().withHeader(buildJWTHeader(algorithm));
return builder;
}
/**
* 校验 Token
*
* @param token
* @return
*/
public Payload verifyToken(String token) {
DecodedJWT jwt = null;
Payload payload = null;
try {
jwt = getDecodedJWT(token);
payload = getPublicClaim(jwt);
payload = getPrivateClaim(jwt, payload);
Map<String, Object> claims = payload.getClaims();
UserBean userBean = Object2MapUtil.map2Bean(claims, UserBean.class);
/* 判断解析出来的对象,是否与 redis 中的对象在属性上是否一致,如果不一致则需要抛出异常 */
UserBean user = (UserBean) redisProvide.get(token);
if (user == null) {
throw new TokenIllegalException(token);
}
if (!Objects.equal(user.getUserName(), userBean.getUserName())) {
throw new TokenMisMatchException(token);
}
} catch (AlgorithmMismatchException e) {
// 算法不一致,将抛出异常
throw e;
} catch (TokenExpiredException e) {
// 令牌失效,将抛出异常
throw e;
} catch (Exception e) {
// 其他异常
throw e;
}
return payload;
}
/**
* 功能描述 : 刷新新的 Token
*
* @param token 老的令牌信息
* @return 开发时间 2019/11/26 0026 下午 1:02
*/
public String refreshToken(String token) {
DecodedJWT jwt = null;
Payload payload = null;
try {
jwt = getDecodedJWT(token);
payload = getPublicClaim(jwt);
payload = getPrivateClaim(jwt, payload);
Map<String, Object> claims = payload.getClaims();
Claim claim = (Claim) claims.get("refreshAt");
// 刷新时间
Date refreshAt = claim.asDate();
// 过期时间
Date expiresAt = payload.getExpiresAt();
Date currentAt = new Date();
// 当前时间未超过过期时间,但是又超过了刷新时间,那么就刷新
if (currentAt.before(expiresAt) && refreshAt.before(currentAt)) {
UserBean userBean = (UserBean) redisProvide.get(token);
Map<String, Object> userInfo = null;
try {
userInfo = Object2MapUtil.bean2Map(userBean);
} catch (IllegalAccessException e) {
throw new CustomerException(CodeEnum.DATAPARSEERROR);
}
redisProvide.del(token);
token = createToken(userInfo, hour, minute);
redisProvide.set(token, userBean);
}
} catch (AlgorithmMismatchException e) {
// 算法不一致,将抛出异常
throw e;
} catch (TokenExpiredException e) {
// 令牌失效,将抛出异常
throw e;
} catch (Exception e) {
// 其他异常
throw e;
}
return token;
}
/**
* 获取 JWT 私有声明
*
* @param jwt
* @param payload
* @return
*/
private Payload getPrivateClaim(DecodedJWT jwt, Payload payload) {
Map<String, Object> claims = new HashMap<String, Object>();
jwt.getClaims().forEach((k, v) -> {
claims.put(k, v);
});
payload.setClaims(claims);
return payload;
}
/**
* 获取 JWT 公共声明
*
* @param jwt
* @return
*/
private Payload getPublicClaim(DecodedJWT jwt) {
Payload payload = new Payload();
payload.setIssuer(jwt.getIssuer());
payload.setSubject(jwt.getSubject());
payload.setAudience(jwt.getAudience());
payload.setIssuedAt(jwt.getIssuedAt());
payload.setExpiresAt(jwt.getExpiresAt());
return payload;
}
/**
* 获取 DecodedJWT
*
* @param token
* @return
*/
private DecodedJWT getDecodedJWT(String token) {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(this.getSecret())).build();
DecodedJWT jwt = verifier.verify(token);
return jwt;
}
/**
* 构建 JWT 头部 Map 信息
*
* @param algorithm
* @return
*/
private Map<String, Object> buildJWTHeader(Algorithm algorithm) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("alg", algorithm.getName());
map.put("typ", "JWT");
return map;
}
/**
* 根据发布时间设置过期时间
* 根据发布时间设置刷新时间
*
* @param issuedAt
* @param hour
* @param payload
*/
public void setIssuedAtAndExpiresAt(Date issuedAt, Integer hour, Integer minute, Payload payload) {
payload.setIssuedAt(issuedAt);
payload.setExpiresAt(getAfterDateByHour(issuedAt, hour));
payload.setRefreshAt(getAfterDateByMinute(issuedAt, minute));
}
/**
* 返回一定时间后的日期
*
* @param date 开始计时的时间
* @param hour 增加的小时
* @return
*/
public Date getAfterDateByHour(Date date, int hour) {
if (date == null) {
date = new Date();
}
Date afterDate = getAfterDate(date, 0, 0, 0, hour, 0, 0);
return afterDate;
}
/**
* 返回一定时间后的日期
*
* @param date 开始计时的时间
* @param minute 增加的分钟
* @return
*/
public Date getAfterDateByMinute(Date date, int minute) {
if (date == null) {
date = new Date();
}
Date afterDate = getAfterDate(date, 0, 0, 0, 0, minute, 0);
return afterDate;
}
/**
* 返回一定时间后的日期
*
* @param date 开始计时的时间
* @param year 增加的年
* @param month 增加的月
* @param day 增加的日
* @param hour 增加的小时
* @param minute 增加的分钟
* @param second 增加的秒
* @return
*/
public Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second) {
if (date == null) {
date = new Date();
}
Calendar cal = new GregorianCalendar();
cal.setTime(date);
if (year != 0) {
cal.add(Calendar.YEAR, year);
}
if (month != 0) {
cal.add(Calendar.MONTH, month);
}
if (day != 0) {
cal.add(Calendar.DATE, day);
}
if (hour != 0) {
cal.add(Calendar.HOUR_OF_DAY, hour);
}
if (minute != 0) {
cal.add(Calendar.MINUTE, minute);
}
if (second != 0) {
cal.add(Calendar.SECOND, second);
}
return cal.getTime();
}
}
主要是增加@EnableConfigurationProperties({RedisConfig.class})
————————————————
原文链接:https://blog.csdn.net/niugang0920/article/details/90711908
网友评论