批量吊销相关对外接口

This commit is contained in:
黎润豪 2026-01-12 17:16:30 +08:00
parent abd9495e83
commit 463cf47066
13 changed files with 604 additions and 0 deletions

View File

@ -0,0 +1,134 @@
package com.chinaweal.aiccs.aiccs.security.controller;
import com.alibaba.fastjson.JSONObject;
import com.chinaweal.aiccs.aiccs.security.entity.PenaltyAppInfo;
import com.chinaweal.aiccs.aiccs.security.entity.dto.LoginInfoParamDto;
import com.chinaweal.aiccs.aiccs.security.entity.dto.PenaltyCaseInfoRequestDto;
import com.chinaweal.aiccs.aiccs.security.entity.vo.SecurityResultVO;
import com.chinaweal.aiccs.aiccs.security.enums.ErrorCode;
import com.chinaweal.aiccs.aiccs.security.service.IPenaltyAppInfoService;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aicorg.exception.CryptException;
import com.chinaweal.aicorg.util.PasswordVerify;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 批量吊销对外接口
*
* @author lroyia
* @since 2026/1/12 15:46
**/
@Slf4j
@RestController
@RequestMapping("/security")
public class PenaltySecurityController {
@Autowired
private TUsersService tUsersService;
@Autowired
private IPenaltyAppInfoService penaltyAppInfoService;
/**
* 登录
*
* @param paramDto 登录参数
* @return 登录结果
*/
@PostMapping("/login")
public Object login(@RequestBody LoginInfoParamDto paramDto) {
String appKey = paramDto.getAppKey();
String appSecret = paramDto.getAppSecret();
if (StringUtils.isBlank(appKey)) {
return SecurityResultVO.error(ErrorCode.APP_KEY_INVALID);
}
if (StringUtils.isBlank(appSecret)) {
return SecurityResultVO.error(ErrorCode.APP_SECRET_INVALID);
}
PenaltyAppInfo byId = penaltyAppInfoService.getById(appKey);
if (byId == null) {
return SecurityResultVO.error(ErrorCode.APP_KEY_INVALID);
}
if (StringUtils.notEquals(byId.getAppSecret(), appSecret)) {
return SecurityResultVO.error(ErrorCode.APP_SECRET_INVALID);
}
if (StringUtils.isBlank(paramDto.getAccount()) || StringUtils.isBlank(paramDto.getPassword())) {
return SecurityResultVO.error(ErrorCode.LOGIN_INFO_INVALID);
}
TUsers one = tUsersService.lambdaQuery().eq(TUsers::getUsername, paramDto.getAccount())
.eq(TUsers::getDeleted, Constant.FALSE_0_STR).eq(TUsers::getLocked, Constant.FALSE_0_STR).last("limit 1").one();
if (one == null) {
return SecurityResultVO.error(ErrorCode.LOGIN_INFO_INVALID);
}
try {
if (StringUtils.notEquals(PasswordVerify.DecodePassword(one.getPassword()), paramDto.getPassword())) {
return SecurityResultVO.error(ErrorCode.LOGIN_INFO_INVALID);
}
} catch (CryptException e) {
log.error("用户密码解密失败", e);
return SecurityResultVO.error(ErrorCode.LOGIN_INFO_INVALID);
}
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(SecurityResultVO.success()));
jsonObject.put("access_token", penaltyAppInfoService.generateAccessToken(byId, one));
return jsonObject;
}
/**
* 登出
*
* @param accessToken accessToken
* @return 操作结果
*/
@PostMapping("/logout")
public SecurityResultVO logout(@RequestParam("access_token") String accessToken) {
penaltyAppInfoService.removeAccessToken(accessToken);
return SecurityResultVO.success();
}
/**
* 批量吊销对外接口
*
* @param requestDto 请求参数
* @return 请求结果
*/
@PostMapping("receiveCaseInfo")
public SecurityResultVO receiveCaseInfo(@RequestParam("access_token") String accessToken,
@RequestBody PenaltyCaseInfoRequestDto requestDto) {
if (!penaltyAppInfoService.existsAccessToken(accessToken)) {
return SecurityResultVO.error(ErrorCode.ACCESS_TOKEN_INVALID);
}
if (StringUtils.isBlank(requestDto.getCaseid())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_0);
}
if (StringUtils.isBlank(requestDto.getCasename())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_1);
}
if (StringUtils.isBlank(requestDto.getCaseintroduction())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_2);
}
if (StringUtils.isBlank(requestDto.getIllegality())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_3);
}
if (StringUtils.isBlank(requestDto.getPenalty())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_4);
}
if (StringUtils.isBlank(requestDto.getPenaltydate())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_5);
}
if (StringUtils.isBlank(requestDto.getPenaltyorg())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_6);
}
if (CollectionUtils.isNotEmpty(requestDto.getPenaltylist())) {
return SecurityResultVO.error(ErrorCode.PARAM_VALID_FAIL_7);
}
// TODO: 接收业务处理
return SecurityResultVO.success();
}
}

View File

@ -0,0 +1,48 @@
package com.chinaweal.aiccs.aiccs.security.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 批量吊销外部应用接入信息
*
* @author lroyia
* @since 2026/1/12 16:25
**/
@Data
@Accessors(chain = true)
@TableName("PENALTY_APP_INFO")
@ApiModel("批量吊销外部应用接入信息")
public class PenaltyAppInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* APP的key
*/
@ApiModelProperty("APP的key")
@TableId(value = "APP_KEY", type = IdType.ASSIGN_UUID)
private String appKey;
/**
* APP访问秘钥
*/
@ApiModelProperty("APP访问秘钥")
@TableField("APP_SECRET")
private String appSecret;
/**
* 外部应用接入描述
*/
@ApiModelProperty("外部应用接入描述")
@TableField("APP_DESCRIPTION")
private String appDescription;
}

View File

@ -0,0 +1,33 @@
package com.chinaweal.aiccs.aiccs.security.entity.dto;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 批量吊销对外登录信息参数
*
* @author lroyia
* @since 2026/1/12 15:43
**/
@Data
@Accessors(chain = true)
public class LoginInfoParamDto implements Serializable {
private static final long serialVersionUID = 1L;
@JSONField(name = "app_key")
private String appKey;
@JSONField(name = "app_secret")
private String appSecret;
@JSONField(name = "account")
private String account;
@JSONField(name = "password")
private String password;
}

View File

@ -0,0 +1,51 @@
package com.chinaweal.aiccs.aiccs.security.entity.dto;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 市场主体信息
*
* @author lroyia
* @since 2026/1/12 17:13
**/
@Data
@Accessors(chain = true)
@ApiModel(value = "市场主体信息")
public class PenaltyCaseInfoEntInfoDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 市场主体身份代码
*/
@JSONField(name = "pripid")
@ApiModelProperty("市场主体身份代码")
private String pripid;
/**
* 统一社会信用代码
*/
@JSONField(name = "uniscid")
@ApiModelProperty("统一社会信用代码")
private String uniscid;
/**
* 法定代表人负责人
*/
@JSONField(name = "legal")
@ApiModelProperty("法定代表人(负责人)")
private String legal;
/**
* 市场主体类型
*/
@JSONField(name = "enttype")
@ApiModelProperty("市场主体类型")
private String enttype;
}

View File

@ -0,0 +1,78 @@
package com.chinaweal.aiccs.aiccs.security.entity.dto;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
*
* @author lroyia
* @since 2026/1/12 16:56
**/
@Data
@Accessors(chain = true)
@ApiModel("批量吊销接口请求参数")
public class PenaltyCaseInfoRequestDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 案件编号
*/
@ApiModelProperty("案件编号")
@JSONField(name = "caseid")
private String caseid;
/**
* 案件名称
*/
@JSONField(name = "casename")
@ApiModelProperty("案件名称")
private String casename;
/**
* 案由
*/
@ApiModelProperty("案由")
@JSONField(name = "caseintroduction")
private String caseintroduction;
/**
* 违法行为
*/
@ApiModelProperty("违法行为")
@JSONField(name = "illegality")
private String illegality;
/**
* 处罚内容
*/
@JSONField(name = "penalty")
@ApiModelProperty("处罚内容")
private String penalty;
/**
* 处罚决定日期yyyy-MM-dd
*/
@JSONField(name = "penaltydate")
@ApiModelProperty("处罚决定日期yyyy-MM-dd")
private String penaltydate;
/**
* 处罚决定机关
*/
@JSONField(name = "penaltyorg")
@ApiModelProperty("处罚决定机关")
private String penaltyorg;
/**
* 吊销市场主体清单
*/
@JSONField(name = "penaltylist")
@ApiModelProperty("吊销市场主体清单")
private List<PenaltyCaseInfoEntInfoDto> penaltylist;
}

View File

@ -0,0 +1,29 @@
package com.chinaweal.aiccs.aiccs.security.entity.vo;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 错误信息VO
*
* @author lroyia
* @since 2026/1/12 15:49
**/
@Data
@Accessors(chain = true)
public class ErrorInfoVO implements Serializable {
private static final long serialVersionUID = 1L;
@JSONField(name = "error_code")
private String errorCode;
@JSONField(name = "name")
private String name;
@JSONField(name = "message")
private String message;
}

View File

@ -0,0 +1,61 @@
package com.chinaweal.aiccs.aiccs.security.entity.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.chinaweal.aiccs.aiccs.security.enums.ErrorCode;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 批量报销板块的ResultVO
*
* @author lroyia
* @since 2026/1/12 15:48
**/
@Data
@Accessors(chain = true)
public class SecurityResultVO implements Serializable {
private static final long serialVersionUID = 1L;
private static final String SUCCESS = "SUCCESS";
private static final String FAILURE = "FAILURE";
@JSONField(name = "ack_code")
private String ackCode;
@JSONField(name = "errors")
private List<ErrorInfoVO> errors;
/**
* 创建请求成功信息
*
* @return 成功
*/
public static SecurityResultVO success() {
SecurityResultVO resultVO = new SecurityResultVO();
resultVO.setAckCode(SUCCESS);
resultVO.errors = new ArrayList<>(0);
return resultVO;
}
/**
* 创建失败返回信息
*
* @return 成功
*/
public static SecurityResultVO error(ErrorCode... codes) {
SecurityResultVO resultVO = new SecurityResultVO();
resultVO.setAckCode(SUCCESS);
resultVO.errors = new ArrayList<>(codes == null ? 0 : codes.length);
if (codes != null) {
for (ErrorCode code : codes) {
resultVO.errors.add(new ErrorInfoVO().setErrorCode(code.getCode()).setName(code.getName()).setMessage(code.getMessage()));
}
}
return resultVO;
}
}

View File

@ -0,0 +1,36 @@
package com.chinaweal.aiccs.aiccs.security.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 错误码枚举
* @author lroyia
* @since 2026/1/12 15:51
**/
@Getter
@AllArgsConstructor
public enum ErrorCode {
APP_KEY_INVALID("12002", "接口登录失败", "app_key无效"),
APP_SECRET_INVALID("12003", "接口登录失败", "app_secret无效"),
LOGIN_INFO_INVALID("12004", "接口登录失败", "登录信息无效"),
ACCESS_TOKEN_INVALID("13000", "accessToken校验", "ACCESS_TOKEN无效"),
PARAM_VALID_FAIL_0("14000", "参数校验失败", "案件编号不能为空"),
PARAM_VALID_FAIL_1("14001", "参数校验失败", "案件名称不能为空"),
PARAM_VALID_FAIL_2("14002", "参数校验失败", "案由不能为空"),
PARAM_VALID_FAIL_3("14003", "参数校验失败", "违法行为不能为空"),
PARAM_VALID_FAIL_4("14004", "参数校验失败", "处罚内容不能为空"),
PARAM_VALID_FAIL_5("14005", "参数校验失败", "处罚决定日期不能为空"),
PARAM_VALID_FAIL_6("14006", "参数校验失败", "处罚决定机关不能为空"),
PARAM_VALID_FAIL_7("14007", "参数校验失败", "吊销市场主体清单不能为空"),
;
private final String code;
private final String name;
private final String message;
}

View File

@ -0,0 +1,13 @@
package com.chinaweal.aiccs.aiccs.security.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.aiccs.aiccs.security.entity.PenaltyAppInfo;
/**
* 批量吊销外部应用接入信息 Mapper
*
* @author lroyia
* @since 2026/1/12 16:29
**/
public interface PenaltyAppInfoMapper extends BaseMapper<PenaltyAppInfo> {
}

View File

@ -0,0 +1,46 @@
package com.chinaweal.aiccs.aiccs.security.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.aiccs.aiccs.security.entity.PenaltyAppInfo;
import com.chinaweal.aiccs.org.entity.TUsers;
/**
* 批量吊销外部应用接入信息 Service
*
* @author lroyia
* @since 2026/1/12 16:30
**/
public interface IPenaltyAppInfoService extends IService<PenaltyAppInfo> {
/**
* 获取用户信息
*
* @param accessToken 当前登录的accessToken
* @return 用户信息
*/
TUsers getUserInfo(String accessToken);
/**
* 生成AccessToken
*
* @param appInfo 应用信息
* @param user 用户信息
* @return 生成结果
*/
String generateAccessToken(PenaltyAppInfo appInfo, TUsers user);
/**
* 删除accessToken
*
* @param accessToken accessToken
*/
void removeAccessToken(String accessToken);
/**
* 校验是否存在accessToken
*
* @param accessToken accessToken
* @return 校验结果
*/
boolean existsAccessToken(String accessToken);
}

View File

@ -0,0 +1,68 @@
package com.chinaweal.aiccs.aiccs.security.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.aiccs.aiccs.security.entity.PenaltyAppInfo;
import com.chinaweal.aiccs.aiccs.security.mapper.PenaltyAppInfoMapper;
import com.chinaweal.aiccs.aiccs.security.service.IPenaltyAppInfoService;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* 批量吊销外部应用接入信息 服务实现类
*
* @author lroyia
* @since 2026/1/12 16:31
**/
@Service
public class PenaltyAppInfoServiceImpl extends ServiceImpl<PenaltyAppInfoMapper, PenaltyAppInfo> implements IPenaltyAppInfoService {
private final static String ACCESS_TOKEN_KEY_PREFIX = "penalty:security:access_token:";
@Autowired
private RedisService redisService;
@Override
public TUsers getUserInfo(String accessToken) {
String key = ACCESS_TOKEN_KEY_PREFIX + accessToken;
if (redisService.exists(key)) {
String jsonStr = redisService.get(key);
if (StringUtils.isBlank(jsonStr)) {
return null;
}
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
return JSONObject.parseObject(jsonObject.getJSONObject("user").toJSONString(), TUsers.class);
}
return null;
}
@Override
public String generateAccessToken(PenaltyAppInfo appInfo, TUsers user) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appInfo", appInfo);
jsonObject.put("user", user);
String accessToken = UUID.randomUUID().toString();
String key = ACCESS_TOKEN_KEY_PREFIX + accessToken;
while (redisService.exists(key)) {
accessToken = UUID.randomUUID().toString();
key = ACCESS_TOKEN_KEY_PREFIX + accessToken;
}
redisService.set(key, jsonObject.toJSONString(), 1800);
return accessToken;
}
@Override
public void removeAccessToken(String accessToken) {
redisService.remove(ACCESS_TOKEN_KEY_PREFIX + accessToken);
}
@Override
public boolean existsAccessToken(String accessToken) {
return redisService.exists(ACCESS_TOKEN_KEY_PREFIX + accessToken);
}
}

View File

@ -44,6 +44,7 @@ public class ShiroConfig {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 设置无权限时跳转的 url; // 设置无权限时跳转的 url;
filterChainDefinitionMap.put("/security/**", DefaultFilter.anon.name());
filterChainDefinitionMap.put("/oauth2/**", DefaultFilter.anon.name()); filterChainDefinitionMap.put("/oauth2/**", DefaultFilter.anon.name());
filterChainDefinitionMap.put("/toincludeabn/saveClue_SSJ", DefaultFilter.anon.name()); filterChainDefinitionMap.put("/toincludeabn/saveClue_SSJ", DefaultFilter.anon.name());
filterChainDefinitionMap.put("/toincludeabn/registration", DefaultFilter.anon.name()); filterChainDefinitionMap.put("/toincludeabn/registration", DefaultFilter.anon.name());

View File

@ -0,0 +1,6 @@
<?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.chinaweal.aiccs.aiccs.security.mapper.PenaltyAppInfoMapper">
</mapper>