【功能优化】全局:LoginUser 新增过期时间,方便判断 token 过期
parent
b728e66282
commit
b0c2f75a3f
|
@ -1,4 +1,4 @@
|
||||||
package cn.iocoder.yudao.framework.jackson.core.databind;
|
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.iocoder.yudao.framework.jackson.core.databind;
|
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.iocoder.yudao.framework.jackson.core.databind;
|
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -42,6 +43,10 @@ public class LoginUser {
|
||||||
* 授权范围
|
* 授权范围
|
||||||
*/
|
*/
|
||||||
private List<String> scopes;
|
private List<String> scopes;
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime expiresTime;
|
||||||
|
|
||||||
// ========== 上下文 ==========
|
// ========== 上下文 ==========
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -96,7 +96,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||||
// 构建登录用户
|
// 构建登录用户
|
||||||
return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
|
return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
|
||||||
.setInfo(accessToken.getUserInfo()) // 额外的用户信息
|
.setInfo(accessToken.getUserInfo()) // 额外的用户信息
|
||||||
.setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes());
|
.setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes())
|
||||||
|
.setExpiresTime(accessToken.getExpiresTime());
|
||||||
} catch (ServiceException serviceException) {
|
} catch (ServiceException serviceException) {
|
||||||
// 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
|
// 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.jackson.config;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
|
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.TimestampLocalDateTimeDeserializer;
|
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.TimestampLocalDateTimeSerializer;
|
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.gateway.filter.security;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -35,5 +36,9 @@ public class LoginUser {
|
||||||
* 授权范围
|
* 授权范围
|
||||||
*/
|
*/
|
||||||
private List<String> scopes;
|
private List<String> scopes;
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime expiresTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.gateway.filter.security;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.gateway.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.gateway.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.gateway.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.gateway.util.WebFrameworkUtils;
|
||||||
|
@ -94,7 +95,8 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
|
||||||
// 重要说明:defaultIfEmpty 作用,保证 Mono.empty() 情况,可以继续执行 `flatMap 的 chain.filter(exchange)` 逻辑,避免返回给前端空的 Response!!
|
// 重要说明:defaultIfEmpty 作用,保证 Mono.empty() 情况,可以继续执行 `flatMap 的 chain.filter(exchange)` 逻辑,避免返回给前端空的 Response!!
|
||||||
return getLoginUser(exchange, token).defaultIfEmpty(LOGIN_USER_EMPTY).flatMap(user -> {
|
return getLoginUser(exchange, token).defaultIfEmpty(LOGIN_USER_EMPTY).flatMap(user -> {
|
||||||
// 1. 无用户,直接 filter 继续请求
|
// 1. 无用户,直接 filter 继续请求
|
||||||
if (user == LOGIN_USER_EMPTY) {
|
if (user == LOGIN_USER_EMPTY || // 下面 expiresTime 的判断,为了解决 token 实际已经过期的情况
|
||||||
|
user.getExpiresTime() == null || LocalDateTimeUtils.afterNow(user.getExpiresTime())) {
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +155,8 @@ public class TokenAuthenticationFilter implements GlobalFilter, Ordered {
|
||||||
OAuth2AccessTokenCheckRespDTO tokenInfo = result.getData();
|
OAuth2AccessTokenCheckRespDTO tokenInfo = result.getData();
|
||||||
return new LoginUser().setId(tokenInfo.getUserId()).setUserType(tokenInfo.getUserType())
|
return new LoginUser().setId(tokenInfo.getUserId()).setUserType(tokenInfo.getUserType())
|
||||||
.setInfo(tokenInfo.getUserInfo()) // 额外的用户信息
|
.setInfo(tokenInfo.getUserInfo()) // 额外的用户信息
|
||||||
.setTenantId(tokenInfo.getTenantId()).setScopes(tokenInfo.getScopes());
|
.setTenantId(tokenInfo.getTenantId()).setScopes(tokenInfo.getScopes())
|
||||||
|
.setExpiresTime(tokenInfo.getExpiresTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package cn.iocoder.yudao.gateway.jackson;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class JacksonAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
|
||||||
|
// 1.1 创建 SimpleModule 对象
|
||||||
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
|
simpleModule
|
||||||
|
// 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
|
||||||
|
.addSerializer(Long.class, NumberSerializer.INSTANCE)
|
||||||
|
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
|
||||||
|
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
|
||||||
|
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
|
||||||
|
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
||||||
|
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||||
|
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||||
|
// 1.2 注册到 objectMapper
|
||||||
|
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||||
|
|
||||||
|
// 2. 设置 objectMapper 到 JsonUtils
|
||||||
|
JsonUtils.init(CollUtil.getFirst(objectMappers));
|
||||||
|
log.info("[init][初始化 JsonUtils 成功]");
|
||||||
|
return new JsonUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.bargain.BargainRecordStatusEnum;
|
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||||
public class CombinationRecordReqPageVO extends PageParam {
|
public class CombinationRecordReqPageVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "活动状态", example = "1")
|
@Schema(description = "活动状态", example = "1")
|
||||||
@InEnum(BargainRecordStatusEnum.class)
|
@InEnum(CombinationRecordStatusEnum.class)
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "团长编号", example = "1024")
|
@Schema(description = "团长编号", example = "1024")
|
||||||
|
|
|
@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -26,4 +27,7 @@ public class OAuth2AccessTokenCheckRespDTO implements Serializable {
|
||||||
@Schema(description = "授权范围的数组", example = "user_info")
|
@Schema(description = "授权范围的数组", example = "user_info")
|
||||||
private List<String> scopes;
|
private List<String> scopes;
|
||||||
|
|
||||||
|
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private LocalDateTime expiresTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ public class OAuth2TokenApiImpl implements OAuth2TokenApi {
|
||||||
private OAuth2TokenService oauth2TokenService;
|
private OAuth2TokenService oauth2TokenService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Operation(description = "创建访问令牌")
|
|
||||||
public CommonResult<OAuth2AccessTokenRespDTO> createAccessToken(OAuth2AccessTokenCreateReqDTO reqDTO) {
|
public CommonResult<OAuth2AccessTokenRespDTO> createAccessToken(OAuth2AccessTokenCreateReqDTO reqDTO) {
|
||||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
|
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
|
||||||
reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId(), reqDTO.getScopes());
|
reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId(), reqDTO.getScopes());
|
||||||
|
|
Loading…
Reference in New Issue