[add]支持其他平台通过ApiKey调用系统相关接口
This commit is contained in:
@@ -51,8 +51,11 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
jwt = request.getParameter(JwtUtils.getHeader());
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
jwt = request.getHeader(JwtUtils.getApiKeyHeader());
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.service.IUserApiKeyService;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import org.jose4j.jwk.JsonWebKey;
|
||||
import org.jose4j.jwk.JsonWebKeySet;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.jose4j.jwk.RsaJwkGenerator;
|
||||
import org.jose4j.jws.AlgorithmIdentifiers;
|
||||
@@ -20,8 +24,18 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class JwtUtils implements InitializingBean {
|
||||
@@ -30,6 +44,8 @@ public class JwtUtils implements InitializingBean {
|
||||
|
||||
public static final String HEADER = "access-token";
|
||||
|
||||
public static final String API_KEY_HEADER = "api-key";
|
||||
|
||||
private static final String AUDIENCE = "Audience";
|
||||
|
||||
private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
|
||||
@@ -37,17 +53,28 @@ public class JwtUtils implements InitializingBean {
|
||||
/**
|
||||
* token过期时间(分钟)
|
||||
*/
|
||||
public static final long expirationTime = 30 * 24 * 60;
|
||||
public static final long EXPIRATION_TIME = 30 * 24 * 60;
|
||||
|
||||
private static RsaJsonWebKey rsaJsonWebKey;
|
||||
|
||||
private static IUserService userService;
|
||||
|
||||
private static IUserApiKeyService userApiKeyService;
|
||||
|
||||
public static String getApiKeyHeader() {
|
||||
return API_KEY_HEADER;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserService(IUserService userService) {
|
||||
JwtUtils.userService = userService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserApiKeyService(IUserApiKeyService userApiKeyService) {
|
||||
JwtUtils.userApiKeyService = userApiKeyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
try {
|
||||
@@ -62,14 +89,38 @@ public class JwtUtils implements InitializingBean {
|
||||
* @throws JoseException JoseException
|
||||
*/
|
||||
private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException {
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
RsaJsonWebKey rsaJsonWebKey = null;
|
||||
try {
|
||||
URL url = getClass().getClassLoader().getResource("jwk.json");
|
||||
if (url != null) {
|
||||
URI uri = url.toURI();
|
||||
Path path = Paths.get(uri);
|
||||
if (Files.exists(path)) {
|
||||
byte[] allBytes = Files.readAllBytes(path);
|
||||
String jwkJson = new String(allBytes, StandardCharsets.UTF_8);
|
||||
final JsonWebKeySet jsonWebKeySet = new JsonWebKeySet(jwkJson);
|
||||
List<JsonWebKey> jsonWebKeys = jsonWebKeySet.getJsonWebKeys();
|
||||
if (!jsonWebKeys.isEmpty()) {
|
||||
JsonWebKey jsonWebKey = jsonWebKeys.get(0);
|
||||
if (jsonWebKey instanceof RsaJsonWebKey) {
|
||||
rsaJsonWebKey = (RsaJsonWebKey) jsonWebKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
// ignored
|
||||
}
|
||||
if (rsaJsonWebKey == null) {
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
}
|
||||
return rsaJsonWebKey;
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
public static String createToken(String username, Long expirationTime, Map<String, Object> extra) {
|
||||
try {
|
||||
/*
|
||||
* “iss” (issuer) 发行人
|
||||
@@ -83,13 +134,17 @@ public class JwtUtils implements InitializingBean {
|
||||
claims.setGeneratedJwtId();
|
||||
claims.setIssuedAtToNow();
|
||||
// 令牌将过期的时间 分钟
|
||||
claims.setExpirationTimeMinutesInTheFuture(expirationTime);
|
||||
if (expirationTime != null) {
|
||||
claims.setExpirationTimeMinutesInTheFuture(expirationTime);
|
||||
}
|
||||
claims.setNotBeforeMinutesInThePast(0);
|
||||
claims.setSubject("login");
|
||||
claims.setAudience(AUDIENCE);
|
||||
//添加自定义参数,必须是字符串类型
|
||||
claims.setClaim("userName", username);
|
||||
|
||||
if (extra != null) {
|
||||
extra.forEach(claims::setClaim);
|
||||
}
|
||||
//jws
|
||||
JsonWebSignature jws = new JsonWebSignature();
|
||||
//签名算法RS256
|
||||
@@ -104,10 +159,17 @@ public class JwtUtils implements InitializingBean {
|
||||
} catch (JoseException e) {
|
||||
logger.error("[Token生成失败]: {}", e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String createToken(String username, Long expirationTime) {
|
||||
return createToken(username, expirationTime, null);
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
return createToken(username, EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
public static String getHeader() {
|
||||
return HEADER;
|
||||
}
|
||||
@@ -118,8 +180,8 @@ public class JwtUtils implements InitializingBean {
|
||||
|
||||
try {
|
||||
JwtConsumer consumer = new JwtConsumerBuilder()
|
||||
.setRequireExpirationTime()
|
||||
.setMaxFutureValidityInMinutes(5256000)
|
||||
//.setRequireExpirationTime()
|
||||
//.setMaxFutureValidityInMinutes(5256000)
|
||||
.setAllowedClockSkewInSeconds(30)
|
||||
.setRequireSubject()
|
||||
//.setExpectedIssuer("")
|
||||
@@ -129,15 +191,27 @@ public class JwtUtils implements InitializingBean {
|
||||
|
||||
JwtClaims claims = consumer.processToClaims(token);
|
||||
NumericDate expirationTime = claims.getExpirationTime();
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
if (expirationTime != null) {
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
Long apiKeyId = claims.getClaimValue("apiKeyId", Long.class);
|
||||
if (apiKeyId != null) {
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(apiKeyId.intValue());
|
||||
if (userApiKey == null || !userApiKey.isEnable()) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
String username = (String) claims.getClaimValue("userName");
|
||||
User user = userService.getUserByUsername(username);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user