token管理相关接口,关联相关接口参数修改

This commit is contained in:
liuzhaotian
2025-03-04 16:16:07 +08:00
parent 2d9db3f370
commit c694e40812
23 changed files with 1111 additions and 41 deletions
@@ -202,6 +202,31 @@
<scope>compile</scope>
</dependency>
<!-- JJWT 依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
@@ -0,0 +1,132 @@
package com.cf.imes.module.system.controller.admin.tokenconfig;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigPageReqVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigRespVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.tokenconfig.TokenConfigDO;
import com.cf.imes.module.system.service.tokenconfig.TokenConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
/**
* @author token配置管理
*/
@Tag(name = "管理后台 - Token管理")
@RestController
@RequestMapping("/system/token")
@Validated
public class TokenConfigController {
@Resource
private TokenConfigService tokenConfigService;
@GetMapping()
@Operation(summary = "获得token配置的分页列表")
// @PreAuthorize("@ss.hasAnyPermissions('system:token:query')")
public CommonResult<PageResult<TokenConfigRespVO>> getTokenConfigPage(@Valid TokenConfigPageReqVO pageReqVO) {
PageResult<TokenConfigRespVO> pageResult = tokenConfigService.getTokenConfigPage(pageReqVO);
return success(pageResult);
}
@GetMapping("/{id}")
@Operation(summary = "根据ID获取对应的token配置信息")
// @PreAuthorize("@ss.hasAnyPermissions('system:token:query')")
public CommonResult<TokenConfigRespVO> getTokenConConfig(@PathVariable("id") Long id) {
TokenConfigDO tokenConConfig = tokenConfigService.getTokenConConfig(id);
return success(BeanUtils.toBean(tokenConConfig, TokenConfigRespVO.class));
}
@PostMapping()
@Operation(summary = "token配置新增")
// @PreAuthorize("@ss.hasAnyPermissions('system:token:create')")
public CommonResult<Boolean> insertTokenConfig(@Valid @RequestBody TokenConfigSaveReqVO reqVO) {
tokenConfigService.insertTokenConfig(reqVO);
return success(true);
}
@PutMapping()
@Operation(summary = "token配置修改")
// @PreAuthorize("@ss.hasAnyPermissions('system:token:update')")
public CommonResult<Boolean> updateTokenConfig(@Valid @RequestBody TokenConfigSaveReqVO reqVO) {
tokenConfigService.updateTokenConfig(reqVO);
return success(true);
}
@DeleteMapping("/{id}")
@Operation(summary = "token配置删除")
// @PreAuthorize("@ss.hasPermission('system:token:delete')")
public CommonResult<Boolean> deleteTokenConfig(@PathVariable("id") Long id) {
tokenConfigService.deleteTokenConfig(id);
return success(true);
}
@GetMapping("/check")
@Operation(summary = "token校验")
// @PreAuthorize("@ss.hasAnyPermissions('system:base-setting:query','unplannedOrders:query','placeorder:query')")
public CommonResult<Long> checkTokenConfig(@RequestParam("token") String token) {
return success(tokenConfigService.checkTokenConfig(token));
}
@GetMapping("/copy")
@Operation(summary = "token复制")
// @PreAuthorize("@ss.hasAnyPermissions('system:base-setting:query','unplannedOrders:query','placeorder:query')")
public CommonResult<String> tokenConfigCopy(@RequestParam("id") Long id) {
return success(tokenConfigService.tokenConfigCopy(id));
}
@GetMapping("/export")
@Operation(summary = "导出配置信息")
// @PreAuthorize("@ss.hasAnyPermissions('system:token:export')")
@OperateLog(type = EXPORT)
public void exportPlateExcel(@Valid TokenConfigPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<TokenConfigRespVO> list = tokenConfigService.getTokenConfigPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "token配置信息表.xls", "数据", TokenConfigRespVO.class,
BeanUtils.toBean(list, TokenConfigRespVO.class));
}
}
@@ -0,0 +1,17 @@
package com.cf.imes.module.system.controller.admin.tokenconfig.vo;
import lombok.Data;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Getter
@Data
public class JwtConfig{
@Value("${jwt.secret}")
private String secret;
}
@@ -0,0 +1,35 @@
package com.cf.imes.module.system.controller.admin.tokenconfig.vo;
import com.cf.imes.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
@Schema(description = "管理后台 - token 配置分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
public class TokenConfigPageReqVO extends PageParam {
@Schema(description = "应用名称")
private String appName;
@Schema(description = "token值")
private String appToken;
@Schema(description = "时间范围", example = "[2022-07-01 ,2022-07-01]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate[] expiresTime;
}
@@ -0,0 +1,65 @@
package com.cf.imes.module.system.controller.admin.tokenconfig.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author token配置
*/
@Schema(description = "管理后台 - token配置 Response VO")
@Data
@ExcelIgnoreUnannotated
public class TokenConfigRespVO {
@Schema(description = "配置编号")
@ExcelProperty("配置编号")
private Long id;
@Schema(description = "应用类型")
@ExcelProperty("应用类型")
private Integer appType;
@Schema(description = "用户名称")
@ExcelProperty("用户名称")
private String appName;
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
private String organName;
@Schema(description = "应用token")
@ExcelProperty("应用token")
private String appToken;
@Schema(description = "过期时间")
@ExcelProperty("过期时间")
private LocalDateTime expiresTime;
@Schema(description = "备注")
@ExcelProperty("备注")
private String remark;
@Schema(description = "组织ID")
@ExcelProperty("组织ID")
private Long organId;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}
@@ -0,0 +1,41 @@
package com.cf.imes.module.system.controller.admin.tokenconfig.vo;
import com.cf.imes.module.system.validation.token.TokenConfigAppTypeEnumValid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author token配置创建/修改
*/
@Schema(description = "管理后台 - Token配置创建/修改 Request VO")
@Data
public class TokenConfigSaveReqVO {
@Schema(description = "token配置ID")
private Long id;
@Schema(description = "应用类型", requiredMode = Schema.RequiredMode.REQUIRED)
@TokenConfigAppTypeEnumValid
private Integer appType;
@Schema(description = "自定义时间")
private String customizeTime;
@Schema(description = "有效时间类型")
private String expiresTimeType;
@Schema(description = "备注")
private String remark;
}
@@ -0,0 +1,62 @@
package com.cf.imes.module.system.dal.dataobject.tokenconfig;
import com.baomidou.mybatisplus.annotation.*;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.time.LocalDateTime;
/**
* @author token 配置管理
*/
@TableName(value = "system_config_token", autoResultMap = true)
@KeySequence("system_config_token_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TokenConfigDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
/**
* 应用类型,1 WebCAD
*/
private Integer appType;
/**
* 用户名称
*/
private String appName;
/**
* 应用token
*/
private String appToken;
/**
* 过期时间
*/
private LocalDateTime expiresTime;
/**
* 备注
*/
private String remark;
/**
* 组织id
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long organId;
}
@@ -122,13 +122,4 @@ public interface OrganMapper extends BaseMapperX<OrganizationDO> {
}
default OrganizationDO selectByOrganIdAndMobile(Long organId,String mobile) {
return selectOne(new LambdaQueryWrapperX<OrganizationDO>()
.eqIfPresent(OrganizationDO::getDeleted,false)
.eq(OrganizationDO::getId,organId)
.eq(OrganizationDO::getContactMobile,mobile));
}
}
@@ -0,0 +1,53 @@
package com.cf.imes.module.system.dal.mysql.tokenconfig;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigPageReqVO;
import com.cf.imes.module.system.dal.dataobject.tokenconfig.TokenConfigDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
/**
* @author token 配置管理mapper
*/
@Mapper
public interface TokenConfigMapper extends BaseMapperX<TokenConfigDO> {
default PageResult<TokenConfigDO> selectConfigPage(TokenConfigPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<TokenConfigDO>()
.eq(TokenConfigDO::getOrganId,getUserOrganId())
.eq(TokenConfigDO::getDeleted,false)
.likeIfPresent(TokenConfigDO::getAppToken,pageReqVO.getAppToken())
.likeIfPresent(TokenConfigDO::getAppName,pageReqVO.getAppName())
.betweenIfPresent(TokenConfigDO::getExpiresTime,pageReqVO.getExpiresTime())
.orderByDesc(TokenConfigDO::getId));
}
List<Integer> selectAppTypeByOrganId(@Param("organId") Long organId);
default List<TokenConfigDO> selectConfigByOrganId(Long organId) {
return selectList(new LambdaQueryWrapperX<TokenConfigDO>()
.eq(TokenConfigDO::getOrganId,organId)
.eq(TokenConfigDO::getDeleted,false));
}
default TokenConfigDO selectByToken(String token) {
return selectOne(new LambdaQueryWrapperX<TokenConfigDO>()
.eq(TokenConfigDO::getAppToken,token));
}
void deleteTokenConfig(@Param("id") Long id);
}
@@ -0,0 +1,46 @@
package com.cf.imes.module.system.enums.token;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author token配置应用类型枚举
*/
@Getter
@AllArgsConstructor
public enum TokenConfigAppTypeEnum {
/**
* WebCAD
*/
WEBCAD(1, "WebCAD");
/**
* 类型
*/
private final Integer type;
/**
* 应用名称
*/
private final String name;
public static TokenConfigAppTypeEnum fromType(Integer type) {
if (type == null) {
return null;
}
for (TokenConfigAppTypeEnum value : values()) {
if (ObjectUtil.equal(value.getType(), type)) {
return value;
}
}
return null;
}
}
@@ -0,0 +1,114 @@
package com.cf.imes.module.system.enums.token;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import static java.time.temporal.ChronoUnit.*;
/**
* @author token有效时间的类型枚举
*/
@Getter
@AllArgsConstructor
public enum TokenExpiresTimeTypeEnum {
PERMANENT("permanent",99,FOREVER,"永久"),
ONEHOURS("1_hour",1, HOURS,"1小时"),
EIGHTHOURS("8_hour",8, HOURS,"8小时"),
TWELVEHOURS("12_hour",12, HOURS,"12小时"),
ONEDAYS("1_day",1, DAYS,"1天"),
SEVENDAYS("7_day",7, DAYS,"7天"),
FIFTEENDAYS("15_day",15, DAYS,"15天"),
ONEMONTHS("1_month",1, MONTHS,"1个月"),
THREEMONTHS("3_month",3, MONTHS,"3个月"),
SIXMONTHS("6_month",6, MONTHS,"6个月");
/**
* 字段类型名称
*/
private final String type;
/**
* 时长
*/
private final Integer value;
/**
* 类型
*/
private final ChronoUnit timeType;
/**
* 总和
*/
private final String name;
public static LocalDateTime adjustTime(String type, LocalDateTime dateTime) {
TokenExpiresTimeTypeEnum typeEnum = null;
for (TokenExpiresTimeTypeEnum value : values()) {
if (ObjectUtil.equal(value.getType(), type)) {
typeEnum = value;
break;
}
}
if(typeEnum == null){
return null;
}
ChronoUnit typeEnumType = typeEnum.getTimeType();
return switch (typeEnumType) {
case FOREVER -> LocalDateTime.of(2999, 1,1, 0, 0, 0);
case YEARS -> dateTime.plusMinutes(typeEnum.getValue());
case HOURS -> dateTime.plusHours(typeEnum.getValue());
case DAYS -> dateTime.plusDays(typeEnum.getValue());
case MONTHS -> dateTime.plusMonths(typeEnum.getValue());
default -> null;
};
}
}
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO;
import com.cf.imes.module.system.dal.dataobject.notify.NotifyMessageDO;
import com.cf.imes.module.system.dal.dataobject.notify.NotifyMessageReadInfoDO;
@@ -15,7 +16,9 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 站内信 Service 实现类
@@ -47,6 +50,7 @@ public class NotifyMessageServiceImpl implements NotifyMessageService {
@Override
public PageResult<NotifyMessageDO> getMyMyNotifyMessagePage(NotifyMessagePageReqVO pageReqVO) {
PageDTO page = new PageDTO(pageReqVO.getPageNo(), pageReqVO.getPageSize());
pageReqVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getCreateTime()));
IPage<NotifyMessageDO> myMyNotifyMessage = notifyMessageMapper.getMyMyNotifyMessage(page, pageReqVO);
return new PageResult<>(myMyNotifyMessage.getRecords(), myMyNotifyMessage.getTotal());
}
@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
@@ -20,30 +21,32 @@ import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.constants.permission.InternalRoleConstants;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSaveReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSimpleRespVO;
import com.cf.imes.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSaveReqVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.JwtConfig;
import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import com.cf.imes.module.system.convert.organ.OrganConvert;
import com.cf.imes.module.system.dal.dataobject.machine.MachineLimitDO;
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.cf.imes.module.system.dal.dataobject.permission.MenuDO;
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
import com.cf.imes.module.system.dal.dataobject.permission.MenuDO;
import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
import com.cf.imes.module.system.dal.dataobject.tokenconfig.TokenConfigDO;
import com.cf.imes.module.system.dal.mysql.machine.MachineLimitMapper;
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
import com.cf.imes.module.system.dal.mysql.tokenconfig.TokenConfigMapper;
import com.cf.imes.module.system.enums.permission.RoleCodeEnum;
import com.cf.imes.module.system.enums.permission.RoleTypeEnum;
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
import com.cf.imes.module.system.service.permission.MenuService;
import com.cf.imes.module.system.service.permission.PermissionService;
import com.cf.imes.module.system.service.permission.RoleService;
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
import com.cf.imes.module.system.service.user.AdminUserService;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -62,6 +65,7 @@ import java.util.*;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.dal.redis.RedisKeyConstants.OAUTH2_ACCESS_TOKEN;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static com.cf.imes.module.system.service.tokenconfig.TokenConfigServiceImpl.generateBaseToken;
import static java.util.Collections.singleton;
/**
@@ -99,6 +103,13 @@ public class OrganServiceImpl implements OrganService {
@Resource
private MachineLimitMapper machineLimitMapper;
@Resource
private TokenConfigMapper tokenConfigMapper;
@Resource
private JwtConfig jwtConfig;
@Resource
private StringRedisTemplate stringRedisTemplate;
@@ -234,7 +245,22 @@ public class OrganServiceImpl implements OrganService {
}
tenant.setPinyinFull(pinyinFull);
tenant.setPinyinInitial(PinYinUtils.convertFirstChar(tenant.getName()));
}
// 如果手机号更新,需要同步更新 token 管理的 token
if(!Objects.equals(tenant.getContactMobile(), updateReqVO.getContactMobile())){
List<TokenConfigDO> tokenConfigDOS = tokenConfigMapper.selectConfigByOrganId(organId);
if(CollUtil.isNotEmpty(tokenConfigDOS)) {
tokenConfigDOS.forEach(f -> {
f.setAppToken(generateBaseToken(organId, updateReqVO.getContactMobile(), f.getAppType(), jwtConfig.getSecret()));
});
tokenConfigMapper.updateBatch(tokenConfigDOS);
}
}
// 更新组织
OrganizationDO updateObj = BeanUtils.toBean(updateReqVO, OrganizationDO.class);
organMapper.updateById(updateObj);
@@ -0,0 +1,33 @@
package com.cf.imes.module.system.service.tokenconfig;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigPageReqVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigRespVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.tokenconfig.TokenConfigDO;
/**
* @author token 配置管理接口
*/
public interface TokenConfigService {
PageResult<TokenConfigRespVO> getTokenConfigPage(TokenConfigPageReqVO pageReqVO);
TokenConfigDO getTokenConConfig(Long id);
void insertTokenConfig(TokenConfigSaveReqVO reqVO);
void updateTokenConfig(TokenConfigSaveReqVO reqVO);
void deleteTokenConfig(Long id);
Long checkTokenConfig(String token);
String tokenConfigCopy(Long id);
}
@@ -0,0 +1,313 @@
package com.cf.imes.module.system.service.tokenconfig;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.date.DateUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.JwtConfig;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigPageReqVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigRespVO;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.TokenConfigSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.tokenconfig.TokenConfigDO;
import com.cf.imes.module.system.dal.mysql.organ.OrganMapper;
import com.cf.imes.module.system.dal.mysql.tokenconfig.TokenConfigMapper;
import com.cf.imes.module.system.enums.token.TokenConfigAppTypeEnum;
import com.cf.imes.module.system.enums.token.TokenExpiresTimeTypeEnum;
import com.cf.imes.module.system.service.organ.OrganService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
/**
* @author 配置管理接口 实现类
*/
@Slf4j
@Service
public class TokenConfigServiceImpl implements TokenConfigService{
@Resource
private TokenConfigMapper tokenConfigMapper;
@Resource
private OrganMapper organMapper;
@Resource
private OrganService organService;
@Resource
private JwtConfig jwtConfig;
@Override
public PageResult<TokenConfigRespVO> getTokenConfigPage(TokenConfigPageReqVO pageReqVO) {
PageResult<TokenConfigDO> pageResult = tokenConfigMapper.selectConfigPage(pageReqVO);
if(CollUtil.isEmpty(pageResult.getList())) {
return new PageResult<>();
}
OrganizationDO organizationDO = organService.validOrgan(getUserOrganId());
PageResult<TokenConfigRespVO> result = BeanUtils.toBean(pageResult, TokenConfigRespVO.class);
result.getList().forEach(f->{
f.setOrganName(organizationDO.getName());
f.setAppToken(maskString(f.getAppToken()));
});
return result;
}
@Override
public TokenConfigDO getTokenConConfig(Long id) {
TokenConfigDO tokenConfigDO = validateTokenConfigExists(id);
tokenConfigDO.setAppToken(maskString(tokenConfigDO.getAppToken()));
return tokenConfigDO;
}
@Override
public void insertTokenConfig(TokenConfigSaveReqVO reqVO) {
Long organId = getUserOrganId();
OrganizationDO organizationDO = organService.validOrgan(organId);
List<Integer> appTypes = tokenConfigMapper.selectAppTypeByOrganId(organId);
if(appTypes.contains(reqVO.getAppType())){
throw exception(TOKEN_APP_TYPE_EXIST);
}
String token = generateBaseToken(organId, organizationDO.getContactMobile(), reqVO.getAppType(), jwtConfig.getSecret());
LocalDateTime adjustedTime;
if (reqVO.getCustomizeTime() != null){
LocalDateTime localDateTime = LocalDate.parse(reqVO.getCustomizeTime()).atStartOfDay();
adjustedTime = localDateTime.withHour(23).withMinute(59).withSecond(59);
}else {
AssertUtils.notEmpty(reqVO.getExpiresTimeType(),TOKEN_EXPIRES_TIME_IS_NULL);
adjustedTime = TokenExpiresTimeTypeEnum.adjustTime(reqVO.getExpiresTimeType(), LocalDateTime.now());
}
tokenConfigMapper.insert(TokenConfigDO.builder()
.appName(TokenConfigAppTypeEnum.fromType(reqVO.getAppType()).getName())
.appToken(token)
.appType(reqVO.getAppType())
.organId(organId)
.expiresTime(adjustedTime)
.remark(reqVO.getRemark())
.build());
}
@Override
public void updateTokenConfig(TokenConfigSaveReqVO reqVO) {
TokenConfigDO tokenConfigDO = validateTokenConfigExists(reqVO.getId());
if(!tokenConfigDO.getAppType().equals(reqVO.getAppType())){
throw exception(TOKEN_APP_TYPE_NO_UPDATE);
}
LocalDateTime adjustedTime = null;
if (reqVO.getCustomizeTime() != null){
LocalDateTime localDateTime = LocalDate.parse(reqVO.getCustomizeTime()).atStartOfDay();
adjustedTime = localDateTime.withHour(23).withMinute(59).withSecond(59);
}else if(reqVO.getExpiresTimeType() != null){
adjustedTime = TokenExpiresTimeTypeEnum.adjustTime(reqVO.getExpiresTimeType(), tokenConfigDO.getCreateTime());
}
if(adjustedTime != null){
if(DateUtils.isExpired(adjustedTime)){
throw exception(TOKEN_EXPIRES_TIME_DATA_ERROR);
}
tokenConfigDO.setExpiresTime(adjustedTime);
}
tokenConfigDO.setRemark(reqVO.getRemark() == null ? tokenConfigDO.getRemark() : reqVO.getRemark());
tokenConfigMapper.updateById(tokenConfigDO);
}
@Override
public void deleteTokenConfig(Long id) {
TokenConfigDO tokenConfigDO = tokenConfigMapper.selectById(id);
if(ObjectUtil.isNull(tokenConfigDO)){
throw exception(TOKEN_DATA_IS_NULL);
}
tokenConfigMapper.deleteTokenConfig(id);
}
@Override
public Long checkTokenConfig(String token) {
TokenConfigDO tokenConfigDO = tokenConfigMapper.selectByToken(token);
if(tokenConfigDO == null){
throw exception(TOKEN_CONFIG_NOT_EXISTS);
}
if (DateUtils.isExpired(tokenConfigDO.getExpiresTime())) {
throw exception(TOKEN_TIME_IS_EXPIRES);
}
Long organId = tokenConfigDO.getOrganId();
OrganizationDO organizationDO = organMapper.selectById(organId);
if (organizationDO == null) {
throw exception(ORGAN_NOT_EXISTS);
}
if (organizationDO.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
throw exception(ORGAN_DISABLE, organizationDO.getName());
}
if (DateUtils.isExpired(organizationDO.getExpireTime())) {
throw exception(ORGAN_EXPIRE, organizationDO.getName());
}
return organId;
}
@Override
public String tokenConfigCopy(Long id) {
TokenConfigDO tokenConfigDO = validateTokenConfigExists(id);
return tokenConfigDO.getAppToken();
}
private TokenConfigDO validateTokenConfigExists(Long id) {
TokenConfigDO tokenConfigDO = tokenConfigMapper.selectById(id);
if (ObjectUtil.isNull(tokenConfigDO)) {
throw exception(TOKEN_CONFIG_NOT_EXISTS);
}
return tokenConfigDO;
}
// token生成
public static String generateToken(Map<String, Object> claims, String base64SecretKey) {
SecretKey secretKey = Keys.hmacShaKeyFor(base64SecretKey.getBytes(StandardCharsets.UTF_8));
return Jwts.builder()
.addClaims(claims)
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}
// 生成token的信息
public static String generateBaseToken(Long organId, String mobile,Integer appType, String base64SecretKey) {
Map<String, Object> claims = new HashMap<>();
claims.put("organId", organId);
claims.put("mobile", mobile);
claims.put("appType",appType);
String token = generateToken(claims, base64SecretKey);
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(token.getBytes());
token = Base64.getEncoder().encodeToString(hash);
}catch (NoSuchAlgorithmException e){
log.error("token二次处理失败"+e.getMessage());
throw exception(INSERT_TOKEN_DATA_ERROR);
}
return token;
}
public static String maskString(String input) {
int length = input.length();
return input.substring(0, 4) + "*".repeat(length - 8) + input.substring(length - 4);
}
// // 安全密钥生成
// public static String generateSecureSecretKey() {
// SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
// return Base64.getEncoder().encodeToString(key.getEncoded());
// }
}
@@ -0,0 +1,28 @@
package com.cf.imes.module.system.validation.token;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* @author token配置管理应用类型注解
*/
@Target({
ElementType.FIELD,
ElementType.PARAMETER,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {TokenConfigAppTypeEnumValidator.class}
)
public @interface TokenConfigAppTypeEnumValid {
String message() default "应用类型错误,请检查";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -0,0 +1,31 @@
package com.cf.imes.module.system.validation.token;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.token.TokenConfigAppTypeEnum;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @author token配置管理应用类型校验器
*/
public class TokenConfigAppTypeEnumValidator implements ConstraintValidator<TokenConfigAppTypeEnumValid, Integer> {
@Override
public void initialize(TokenConfigAppTypeEnumValid constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
TokenConfigAppTypeEnum configTypeEnum = TokenConfigAppTypeEnum.fromType(value);
if (ObjectUtil.isNotNull(configTypeEnum)) {
return true;
}
return false;
}
}
@@ -43,6 +43,12 @@ knife4j:
setting:
language: zh_cn
# JWT 密钥配置
jwt:
secret: BjEM0tnL3W5zYLQ6pllol49uYVXe+f66pHyOM/tkGWg=
# MyBatis Plus 的配置项
mybatis-plus:
configuration:
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cf.imes.module.system.dal.mysql.tokenconfig.TokenConfigMapper">
<select id="selectAppTypeByOrganId" resultType="java.lang.Integer">
select distinct app_type
from system_config_token
where organ_id = #{organId}
and deleted = false;
</select>
<delete id="deleteTokenConfig">
delete from system_config_token where id = #{id};
</delete>
</mapper>