合并董潘祥冲突
This commit is contained in:
@@ -8,42 +8,29 @@ spring:
|
|||||||
primary: master
|
primary: master
|
||||||
datasource:
|
datasource:
|
||||||
master:
|
master:
|
||||||
<<<<<<< HEAD
|
|
||||||
# MYSQL数据库 主库,业务库
|
# MYSQL数据库 主库,业务库
|
||||||
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
||||||
=======
|
|
||||||
# MYSQL数据库 主库,业务库
|
|
||||||
url: jdbc:mysql://127.0.0.1:3306/gr_repoort001?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
|
||||||
>>>>>>> 20260204
|
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: qihua
|
||||||
lideeyunji: # 从库,框架库
|
lideeyunji: # 从库,框架库
|
||||||
<<<<<<< HEAD
|
url: jdbc:mysql://10.9.0.16:3307/gr_repoort?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&lowerCaseTableNames=1 # MySQL Connector/J 8.X 连接的示例
|
||||||
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
|
||||||
=======
|
|
||||||
url: jdbc:mysql://127.0.0.1:3306/gr_repoort001?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
|
||||||
>>>>>>> 20260204
|
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: qihua
|
||||||
slave: # 日志库单独
|
slave: # 日志库单独
|
||||||
lazy: true # 开启懒加载,保证启动速度
|
lazy: true # 开启懒加载,保证启动速度
|
||||||
<<<<<<< HEAD
|
url: jdbc:mysql://10.9.0.16:3307/gr_repoort?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&lowerCaseTableNames=1 # MySQL Connector/J 8.X 连接的示例
|
||||||
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: qihua
|
||||||
bidb: # 日志库单独
|
bidb: # 日志库单独
|
||||||
lazy: true # 开启懒加载,保证启动速度
|
lazy: true # 开启懒加载,保证启动速度
|
||||||
url: jdbc:mysql://127.0.0.1:3306/erp_bi_data?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
url: jdbc:mysql://127.0.0.1:3306/erp_bi_data?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
||||||
=======
|
|
||||||
url: jdbc:mysql://127.0.0.1:3306/gr_repoort001?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
|
|
||||||
>>>>>>> 20260204
|
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: qihua
|
||||||
redis:
|
redis:
|
||||||
host: 127.0.0.1 # 地址
|
host: 10.9.0.116 # 地址
|
||||||
port: 6379 # 端口
|
port: 6379 # 端口
|
||||||
database: 2 # 数据库索引
|
database: 2 # 数据库索引
|
||||||
password: lidee@123 # 密码,建议生产环境开启
|
password: 123456 # 密码,建议生产环境开启
|
||||||
|
|
||||||
--- #################### 地代码平台相关配置 ####################
|
--- #################### 地代码平台相关配置 ####################
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package com.lideeyunji.service.system.entity;
|
||||||
|
|
||||||
|
import com.lideeyunji.tool.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.lideeyunji.tool.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import com.lideeyunji.service.system.enums.OAuth2GrantTypeEnum;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 客户端 DO
|
||||||
|
*
|
||||||
|
* @author 金灯剑客
|
||||||
|
*/
|
||||||
|
@TableName(value = "system_oauth2_client", autoResultMap = true)
|
||||||
|
@KeySequence("system_oauth2_client_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class OAuth2ClientDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号,数据库自增
|
||||||
|
*
|
||||||
|
* 由于 SQL Server 在存储 String 主键有点问题,所以暂时使用 Long 类型
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 客户端编号
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
/**
|
||||||
|
* 客户端密钥
|
||||||
|
*/
|
||||||
|
private String secret;
|
||||||
|
/**
|
||||||
|
* 应用名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 应用分类
|
||||||
|
*/
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用图标
|
||||||
|
*/
|
||||||
|
private String logo;
|
||||||
|
/**
|
||||||
|
* 应用描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link CommonStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 访问令牌的有效期
|
||||||
|
*/
|
||||||
|
private Integer accessTokenValiditySeconds;
|
||||||
|
/**
|
||||||
|
* 刷新令牌的有效期
|
||||||
|
*/
|
||||||
|
private Integer refreshTokenValiditySeconds;
|
||||||
|
// /**
|
||||||
|
// * 可重定向的 URI 地址
|
||||||
|
// */
|
||||||
|
// @TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
// private List<String> redirectUris;
|
||||||
|
|
||||||
|
private String redirectUris;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型(模式)
|
||||||
|
*
|
||||||
|
* 枚举 {@link OAuth2GrantTypeEnum}
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private List<String> authorizedGrantTypes;
|
||||||
|
/**
|
||||||
|
* 授权范围
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private List<String> scopes;
|
||||||
|
/**
|
||||||
|
* 自动授权的 Scope
|
||||||
|
*
|
||||||
|
* code 授权时,如果 scope 在这个范围内,则自动通过
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private List<String> autoApproveScopes;
|
||||||
|
/**
|
||||||
|
* 权限
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private List<String> authorities;
|
||||||
|
/**
|
||||||
|
* 资源
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private List<String> resourceIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调URI地址
|
||||||
|
*/
|
||||||
|
private String callbackUris;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附加信息,JSON 格式
|
||||||
|
*/
|
||||||
|
private String additionalInformation;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package com.lideeyunji.service.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import com.lideeyunji.tool.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.lideeyunji.tool.framework.common.pojo.PageResult;
|
||||||
|
import com.lideeyunji.tool.framework.common.util.object.BeanUtils;
|
||||||
|
import com.lideeyunji.tool.framework.common.util.string.StrUtils;
|
||||||
|
import com.lideeyunji.service.system.controller.vo.oauth2.client.OAuth2ClientPageReqVO;
|
||||||
|
import com.lideeyunji.service.system.controller.vo.oauth2.client.OAuth2ClientSaveReqVO;
|
||||||
|
import com.lideeyunji.service.system.entity.OAuth2ClientDO;
|
||||||
|
import com.lideeyunji.service.system.mapper.OAuth2ClientMapper;
|
||||||
|
import com.lideeyunji.service.system.config.redis.RedisKeyConstants;
|
||||||
|
import com.lideeyunji.service.system.service.IOAuth2ClientService;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static com.lideeyunji.tool.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static com.lideeyunji.service.system.constant.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2.0 Client Service 实现类
|
||||||
|
*
|
||||||
|
* @author 金灯剑客
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class OAuth2ClientServiceImpl implements IOAuth2ClientService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OAuth2ClientMapper oauth2ClientMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createOAuth2Client(OAuth2ClientSaveReqVO createReqVO) {
|
||||||
|
validateClientIdExists(null, createReqVO.getClientId());
|
||||||
|
// 插入
|
||||||
|
OAuth2ClientDO client = BeanUtils.toBean(createReqVO, OAuth2ClientDO.class);
|
||||||
|
oauth2ClientMapper.insert(client);
|
||||||
|
return client.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为可能修改到 clientId 字段,不好清理
|
||||||
|
public void updateOAuth2Client(OAuth2ClientSaveReqVO updateReqVO) {
|
||||||
|
// 校验存在
|
||||||
|
validateOAuth2ClientExists(updateReqVO.getId());
|
||||||
|
// 校验 Client 未被占用
|
||||||
|
validateClientIdExists(updateReqVO.getId(), updateReqVO.getClientId());
|
||||||
|
|
||||||
|
// 更新
|
||||||
|
OAuth2ClientDO updateObj = BeanUtils.toBean(updateReqVO, OAuth2ClientDO.class);
|
||||||
|
oauth2ClientMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT,
|
||||||
|
allEntries = true) // allEntries 清空所有缓存,因为 id 不是直接的缓存 key,不好清理
|
||||||
|
public void deleteOAuth2Client(Long id) {
|
||||||
|
// 校验存在
|
||||||
|
validateOAuth2ClientExists(id);
|
||||||
|
// 删除
|
||||||
|
oauth2ClientMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateOAuth2ClientExists(Long id) {
|
||||||
|
if (oauth2ClientMapper.selectById(id) == null) {
|
||||||
|
throw exception(OAUTH2_CLIENT_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void validateClientIdExists(Long id, String clientId) {
|
||||||
|
OAuth2ClientDO client = oauth2ClientMapper.selectByClientId(clientId);
|
||||||
|
if (client == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果 id 为空,说明不用比较是否为相同 id 的客户端
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(OAUTH2_CLIENT_EXISTS);
|
||||||
|
}
|
||||||
|
if (!client.getId().equals(id)) {
|
||||||
|
throw exception(OAUTH2_CLIENT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth2ClientDO getOAuth2Client(Long id) {
|
||||||
|
return oauth2ClientMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Cacheable(cacheNames = RedisKeyConstants.OAUTH_CLIENT, key = "#clientId",
|
||||||
|
unless = "#result == null")
|
||||||
|
public OAuth2ClientDO getOAuth2ClientFromCache(String clientId) {
|
||||||
|
return oauth2ClientMapper.selectByClientId(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<OAuth2ClientDO> getOAuth2ClientPage(OAuth2ClientPageReqVO pageReqVO) {
|
||||||
|
return oauth2ClientMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, String authorizedGrantType,
|
||||||
|
Collection<String> scopes, String redirectUri) {
|
||||||
|
// 校验客户端存在、且开启
|
||||||
|
OAuth2ClientDO client = getSelf().getOAuth2ClientFromCache(clientId);
|
||||||
|
if (client == null) {
|
||||||
|
throw exception(OAUTH2_CLIENT_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
if (CommonStatusEnum.isDisable(client.getStatus())) {
|
||||||
|
throw exception(OAUTH2_CLIENT_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验客户端密钥
|
||||||
|
if (StrUtil.isNotEmpty(clientSecret) && ObjectUtil.notEqual(client.getSecret(), clientSecret)) {
|
||||||
|
throw exception(OAUTH2_CLIENT_CLIENT_SECRET_ERROR);
|
||||||
|
}
|
||||||
|
// 校验授权方式
|
||||||
|
if (StrUtil.isNotEmpty(authorizedGrantType) && !CollUtil.contains(client.getAuthorizedGrantTypes(), authorizedGrantType)) {
|
||||||
|
throw exception(OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 校验授权范围
|
||||||
|
if (CollUtil.isNotEmpty(scopes) && !CollUtil.containsAll(client.getScopes(), scopes)) {
|
||||||
|
throw exception(OAUTH2_CLIENT_SCOPE_OVER);
|
||||||
|
}
|
||||||
|
// 校验回调地址
|
||||||
|
// if (StrUtil.isNotEmpty(redirectUri) && !StrUtils.startWithAny(redirectUri, client.getRedirectUris())) {
|
||||||
|
// throw exception(OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, redirectUri);
|
||||||
|
// }
|
||||||
|
if (StrUtil.isNotEmpty(redirectUri) && ObjectUtil.notEqual(client.getRedirectUris(), redirectUri)) {
|
||||||
|
throw exception(OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, redirectUri);
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得自身的代理对象,解决 AOP 生效问题
|
||||||
|
*
|
||||||
|
* @return 自己
|
||||||
|
*/
|
||||||
|
private OAuth2ClientServiceImpl getSelf() {
|
||||||
|
return SpringUtil.getBean(getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user