开始重构 system 模块的代码,先修改认证逻辑
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.system.biz.bo.account;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 账号信息 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AccountBO {
|
||||
|
||||
/**
|
||||
* 账号编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 登陆密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.system.biz.bo.account;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 账号模块 - 用户名登陆 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AccountUsernameAuthorizeBO {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.system.biz.bo.admin;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 管理员模块 - 账号信息 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminBO {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 真实名字
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.mall.system.biz.bo.ouath2;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* TODO 注释
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenBO {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
/**
|
||||
* 账号编号
|
||||
*/
|
||||
private Integer accountId;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expiresTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.system.biz.bo;
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.mall.system.biz.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@MapperScan("cn.iocoder.mall.system.biz.dao") // 扫描对应的 Mapper 接口
|
||||
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理。为什么使用 proxyTargetClass 参数,参见 https://blog.csdn.net/huang_550/article/details/76492600
|
||||
public class DatabaseConfiguration {
|
||||
|
||||
// 数据库连接池 Druid
|
||||
|
||||
@Bean
|
||||
public ISqlInjector sqlInjector() {
|
||||
return new DefaultSqlInjector(); // MyBatis Plus 逻辑删除
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor(); // MyBatis Plus 分页插件
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.mall.system.biz.config;
|
||||
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.mall.system.biz.constant.SystemErrorCodeEnum;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
@Configuration
|
||||
public class ServiceExceptionConfiguration {
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html
|
||||
public void initMessages() {
|
||||
for (SystemErrorCodeEnum item : SystemErrorCodeEnum.values()) {
|
||||
ServiceExceptionUtil.put(item.getCode(), item.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package cn.iocoder.mall.system.biz.constant;
|
||||
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
|
||||
/**
|
||||
* 错误码枚举类
|
||||
*
|
||||
* system 系统,使用 1-002-000-000 段
|
||||
*/
|
||||
public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
|
||||
|
||||
// ========== OAUTH2 模块 ==========
|
||||
OAUTH2_UNKNOWN(1001001000, "未知错误"), // 预留
|
||||
OAUTH2_ACCOUNT_NOT_FOUND(1001001001, "账号不存在"),
|
||||
OAUTH2_ACCOUNT_PASSWORD_ERROR(1001001002, "密码不正确"),
|
||||
//// OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到
|
||||
//// OAUTH2_INVALID_GRANT(1001001010, ""), // 预留
|
||||
// OAUTH2_INVALID_TOKEN_NOT_FOUND(1002001011, "访问令牌不存在"),
|
||||
// OAUTH2_INVALID_TOKEN_EXPIRED(1002001012, "访问令牌已过期"),
|
||||
// OAUTH2_INVALID_TOKEN_INVALID(1002001013, "访问令牌已失效"),
|
||||
// OAUTH2_NOT_LOGIN(1002001015, "账号未登陆"),
|
||||
// OAUTH2_INVALID_TOKEN_ERROR_USER_TYPE(1002001016, "访问令牌用户类型不正确"),
|
||||
// OAUTH_INVALID_REFRESH_TOKEN_NOT_FOUND(1002001017, "刷新令牌不存在"),
|
||||
// OAUTH_INVALID_REFRESH_TOKEN_EXPIRED(1002001018, "访问令牌已过期"),
|
||||
// OAUTH_INVALID_REFRESH_TOKEN_INVALID(1002001019, "刷新令牌已失效"),
|
||||
|
||||
|
||||
// ========== 管理员模块 1002002000 ==========
|
||||
ADMIN_NOT_FOUND(1002002000, "管理员不存在"),
|
||||
// 废弃 ADMIN_USERNAME_NOT_REGISTERED(1002002000, "账号不存在"),
|
||||
// 废弃 ADMIN_PASSWORD_ERROR(1002002001, "密码不正确"),
|
||||
// ADMIN_IS_DISABLE(1002002002, "账号被禁用"),
|
||||
// ADMIN_USERNAME_EXISTS(1002002002, "账号已经存在"),
|
||||
// ADMIN_STATUS_EQUALS(1002002003, "账号已经是该状态"),
|
||||
// ADMIN_DELETE_ONLY_DISABLE(1002002004, "只有关闭的账号才可以删除"),
|
||||
// ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE(1002002005, "管理员的账号状态不允许变更"),
|
||||
// ADMIN_ASSIGN_ROLE_NOT_EXISTS(1002002006, "分配员工角色时,有角色不存在"),
|
||||
// ADMIN_INVALID_PERMISSION(1002002007, "没有该操作权限"),
|
||||
// ADMIN_ADMIN_CAN_NOT_UPDATE(1002002008, "管理员的账号不允许变更"),
|
||||
// ADMIN_DEMO_CAN_NOT_WRITE(1002002009, "演示账号,暂不允许写操作。欢迎加入我们的交流群:http://t.cn/EKEr5WE"),
|
||||
|
||||
// ========== 资源模块 1002003000 ==========
|
||||
// RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
||||
// RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
|
||||
// RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
|
||||
// RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
|
||||
// RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
|
||||
// RESOURCE_PARENT_NOT_MENU(1002003005, "父资源的类型必须是菜单"),
|
||||
|
||||
// ========== 角色模块 1002004000 ==========
|
||||
// ROLE_NOT_EXISTS(1002004000, "角色不存在"),
|
||||
// ROLE_ASSIGN_RESOURCE_NOT_EXISTS(1002004001, "分配角色资源时,有资源不存在"),
|
||||
|
||||
// ========== 数据字典模块 1002005000 ==========
|
||||
// DATA_DICT_EXISTS(1002005000, "该数据字典已经存在"),
|
||||
// DATA_DICT_NOT_EXISTS(1002005001, "该数据字典不存在"),
|
||||
|
||||
// ========== 短信模板 1002006000 ==========
|
||||
// SMS_PLATFORM_FAIL(1002006000, "短信平台调用失败【具体错误会动态替换】"),
|
||||
// SMS_SIGN_NOT_EXISTENT(1002006001, "短信签名不存在"),
|
||||
// SMS_SIGN_IS_EXISTENT(1002006002, "短信签名已存在"),
|
||||
// SMS_TEMPLATE_NOT_EXISTENT(1002006020, "短信签名不存在"),
|
||||
// SMS_TEMPLATE_IS_EXISTENT(1002006021, "短信签名不存在"),
|
||||
// SMS_NOT_SEND_CLIENT(1002006030, "短信没有发送的client"),
|
||||
|
||||
// ========== 部门模块 1002007000 ==========
|
||||
// DEPT_SAME_LEVEL_NAME_EXITS(1002007001,"当前级别部门名字已存在"),
|
||||
// DEPT_PARENT_NOT_EXITS(1002007002,"父级部门不存在"),
|
||||
// DEPT_NOT_EXITS(1002007003, "当前部门不存在"),
|
||||
// DEPT_EXITS_CHILDREN(1002007004, "当前部门存在子部门"),
|
||||
// DEPT_PARENT_NOT_LEGAL(1002007005, "父级部门不合法"),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String message;
|
||||
|
||||
SystemErrorCodeEnum(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.mall.system.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface AccountConvert {
|
||||
|
||||
AccountConvert INSTANCE = Mappers.getMapper(AccountConvert.class);
|
||||
|
||||
AccountBO convert(AccountDO accountDO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.mall.system.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface AdminConvert {
|
||||
|
||||
AdminConvert INSTANCE = Mappers.getMapper(AdminConvert.class);
|
||||
|
||||
AdminBO convert(AdminDO adminDO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.mall.system.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2Convert {
|
||||
|
||||
OAuth2Convert INSTANCE = Mappers.getMapper(OAuth2Convert.class);
|
||||
|
||||
OAuth2AccessTokenBO convert(OAuth2AccessTokenDO accessTokenDO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.mall.system.biz.dao.account;
|
||||
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AccountMapper extends BaseMapper<AccountDO> {
|
||||
|
||||
default AccountDO selectByUsername(String username) {
|
||||
return selectOne(new QueryWrapper<AccountDO>()
|
||||
.eq("username", username)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.iocoder.mall.system.biz.dao.admin;
|
||||
|
||||
import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AdminMapper extends BaseMapper<AdminDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.iocoder.mall.system.biz.dao.oauth2;
|
||||
|
||||
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface OAuth2AccessTokenMapper extends BaseMapper<OAuth2AccessTokenDO> {
|
||||
|
||||
default int updateToInvalid(Integer accountId) {
|
||||
QueryWrapper<OAuth2AccessTokenDO> query = new QueryWrapper<OAuth2AccessTokenDO>()
|
||||
.eq("account_id", accountId)
|
||||
.eq("valid", true);
|
||||
return update(new OAuth2AccessTokenDO().setValid(false), query);
|
||||
}
|
||||
|
||||
default int updateToInvalidByRefreshToken(String refreshToken) {
|
||||
QueryWrapper<OAuth2AccessTokenDO> query = new QueryWrapper<OAuth2AccessTokenDO>()
|
||||
.eq("refresh_token", refreshToken).eq("valid", true);
|
||||
return update(new OAuth2AccessTokenDO().setValid(false), query);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.mall.system.biz.dao.oauth2;
|
||||
|
||||
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2RefreshTokenDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface OAuth2RefreshTokenMapper extends BaseMapper<OAuth2RefreshTokenDO> {
|
||||
|
||||
default int updateToInvalid(Integer accountId) {
|
||||
QueryWrapper<OAuth2RefreshTokenDO> query = new QueryWrapper<OAuth2RefreshTokenDO>()
|
||||
.eq("account_id", accountId)
|
||||
.eq("valid", true);
|
||||
return update(new OAuth2RefreshTokenDO().setValid(false), query);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.account;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 账号实体
|
||||
*/
|
||||
@TableName(value = "account")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class AccountDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 账号编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
/**
|
||||
* 密码
|
||||
*
|
||||
* // TODO 芋艿 暂时明文
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 账号状态
|
||||
*
|
||||
* {@link cn.iocoder.common.framework.constant.CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建 IP
|
||||
*/
|
||||
private String createIp;
|
||||
/**
|
||||
* 最后登陆时间
|
||||
*/
|
||||
private Date lastLoginTime;
|
||||
/**
|
||||
* 最后登陆 IP
|
||||
*/
|
||||
private String lastLoginIp;
|
||||
/**
|
||||
* 登陆次数
|
||||
*/
|
||||
private Integer loginTimes;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.admin;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 管理员实体
|
||||
*/
|
||||
@TableName(value = "admin")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class AdminDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 账号编号
|
||||
*
|
||||
* 关联 {@link AccountDO#getId()}
|
||||
*/
|
||||
private Integer accountId;
|
||||
/**
|
||||
* 真实名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 科室编号
|
||||
*
|
||||
* 关联 {@link DepartmentDO#getId()}
|
||||
*/
|
||||
private Integer departmentId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.admin;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 部门实体
|
||||
*/
|
||||
@TableName(value = "department")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class DepartmentDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 部门编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 父级部门编号
|
||||
*/
|
||||
private Integer pid;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.oauth2;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* OAuth2 访问令牌
|
||||
*/
|
||||
@TableName("oauth2_access_token")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
/**
|
||||
* 刷新令牌
|
||||
*
|
||||
* 关联 {@link OAuth2RefreshTokenDO#getId()}
|
||||
*/
|
||||
private String refreshToken;
|
||||
/**
|
||||
* 账号编号
|
||||
*
|
||||
* 关联 {@link AccountDO#getId()}
|
||||
*/
|
||||
private Integer accountId;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expiresTime;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private Boolean valid;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.oauth2;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* OAuth2 刷新令牌
|
||||
*
|
||||
* idx_uid
|
||||
*/
|
||||
@TableName("oauth2_refresh_token")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2RefreshTokenDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
/**
|
||||
* 账号编号
|
||||
*
|
||||
* 关联 {@link AccountDO#getId()}
|
||||
*/
|
||||
private Integer accountId;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private Boolean valid;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expiresTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.system.biz.dataobject.user;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 用户实体
|
||||
*/
|
||||
@TableName(value = "user")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class UserDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 账号编号
|
||||
*
|
||||
* 关联 {@link AccountDO#getId()}
|
||||
*/
|
||||
private Integer accountId;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.mall.system.biz.dto.oatuh2;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
// TODO 注释
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2UsernameAuthenticateDTO {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.system.biz.dto;
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.mall.system.biz.service.account;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
|
||||
|
||||
/**
|
||||
* 账号 Service 接口
|
||||
*/
|
||||
public interface AccountService {
|
||||
|
||||
AccountBO getByUsername(String username);
|
||||
|
||||
boolean matchPassword(String rawPassword, String encodedPassword);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.system.biz.service.account.impl;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
|
||||
import cn.iocoder.mall.system.biz.convert.AccountConvert;
|
||||
import cn.iocoder.mall.system.biz.dao.account.AccountMapper;
|
||||
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
|
||||
import cn.iocoder.mall.system.biz.service.account.AccountService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class AccountServiceImpl implements AccountService {
|
||||
|
||||
@Autowired
|
||||
private AccountMapper accountMapper;
|
||||
|
||||
@Override
|
||||
public AccountBO getByUsername(String username) {
|
||||
AccountDO accountDO = accountMapper.selectByUsername(username);
|
||||
return AccountConvert.INSTANCE.convert(accountDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchPassword(String rawPassword, String encodedPassword) {
|
||||
return Objects.equals(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.iocoder.mall.system.biz.service.admin;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
|
||||
|
||||
public interface AdminService {
|
||||
|
||||
AdminBO get(Integer id);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.system.biz.service.admin.impl;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
|
||||
import cn.iocoder.mall.system.biz.convert.AdminConvert;
|
||||
import cn.iocoder.mall.system.biz.dao.admin.AdminMapper;
|
||||
import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO;
|
||||
import cn.iocoder.mall.system.biz.service.admin.AdminService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AdminServiceImpl implements AdminService {
|
||||
|
||||
@Autowired
|
||||
private AdminMapper adminMapper;
|
||||
|
||||
@Override
|
||||
public AdminBO get(Integer id) {
|
||||
AdminDO adminDO = adminMapper.selectById(id);
|
||||
return AdminConvert.INSTANCE.convert(adminDO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.iocoder.mall.system.biz.service.oauth2;
|
||||
|
||||
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
|
||||
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
|
||||
|
||||
/**
|
||||
* OAuth2 Service 接口
|
||||
*/
|
||||
public interface OAuth2Service {
|
||||
|
||||
OAuth2AccessTokenBO authenticate(OAuth2UsernameAuthenticateDTO usernameAuthenticateDTO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package cn.iocoder.mall.system.biz.service.oauth2.impl;
|
||||
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
|
||||
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
|
||||
import cn.iocoder.mall.system.biz.convert.OAuth2Convert;
|
||||
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2AccessTokenMapper;
|
||||
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2RefreshTokenMapper;
|
||||
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2RefreshTokenDO;
|
||||
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
|
||||
import cn.iocoder.mall.system.biz.service.account.AccountService;
|
||||
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import static cn.iocoder.mall.system.biz.constant.SystemErrorCodeEnum.OAUTH2_ACCOUNT_NOT_FOUND;
|
||||
import static cn.iocoder.mall.system.biz.constant.SystemErrorCodeEnum.OAUTH2_ACCOUNT_PASSWORD_ERROR;
|
||||
|
||||
@Service
|
||||
public class OAuth2ServiceImpl implements OAuth2Service {
|
||||
|
||||
/**
|
||||
* 访问令牌过期时间,单位:毫秒
|
||||
*/
|
||||
@Value("${modules.oauth2-code-service.access-token-expire-time-millis}")
|
||||
private int accessTokenExpireTimeMillis;
|
||||
/**
|
||||
* 刷新令牌过期时间,单位:毫秒
|
||||
*/
|
||||
@Value("${modules.oauth2-code-service.refresh-token-expire-time-millis}")
|
||||
private int refreshTokenExpireTimeMillis;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private OAuth2AccessTokenMapper oauth2AccessTokenMapper;
|
||||
@Autowired
|
||||
private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OAuth2AccessTokenBO authenticate(OAuth2UsernameAuthenticateDTO usernameAuthenticateDTO) {
|
||||
// 获得账号
|
||||
AccountBO accountBO = accountService.getByUsername(usernameAuthenticateDTO.getUsername());
|
||||
if (accountBO == null) {
|
||||
throw ServiceExceptionUtil.exception(OAUTH2_ACCOUNT_NOT_FOUND);
|
||||
}
|
||||
// 校验密码
|
||||
if (!accountService.matchPassword(usernameAuthenticateDTO.getPassword(), accountBO.getPassword())) {
|
||||
throw ServiceExceptionUtil.exception(OAUTH2_ACCOUNT_PASSWORD_ERROR);
|
||||
}
|
||||
// 创建刷新令牌 + 访问令牌
|
||||
OAuth2RefreshTokenDO oauth2RefreshTokenDO = createOAuth2RefreshToken(accountBO.getId());
|
||||
OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(accountBO.getId(), oauth2RefreshTokenDO.getId());
|
||||
// 返回访问令牌
|
||||
return OAuth2Convert.INSTANCE.convert(oauth2AccessTokenDO);
|
||||
}
|
||||
|
||||
private OAuth2AccessTokenDO createOAuth2AccessToken(Integer accountId, String refreshToken) {
|
||||
OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO()
|
||||
.setId(generateAccessToken())
|
||||
.setAccountId(accountId)
|
||||
.setRefreshToken(refreshToken)
|
||||
.setExpiresTime(new Date(System.currentTimeMillis() + accessTokenExpireTimeMillis))
|
||||
.setValid(true);
|
||||
oauth2AccessTokenMapper.insert(accessToken);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
private OAuth2RefreshTokenDO createOAuth2RefreshToken(Integer accountId) {
|
||||
OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO()
|
||||
.setId(generateRefreshToken())
|
||||
.setAccountId(accountId)
|
||||
.setExpiresTime(new Date(System.currentTimeMillis() + refreshTokenExpireTimeMillis))
|
||||
.setValid(true);
|
||||
oauth2RefreshTokenMapper.insert(refreshToken);
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
private String generateAccessToken() {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
||||
private String generateRefreshToken() {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
||||
}
|
||||
4
system/system-biz/src/main/resources/biz.properties
Normal file
4
system/system-biz/src/main/resources/biz.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
##################### 业务模块 #####################
|
||||
## OAuth2CodeService
|
||||
modules.oauth2-code-service.access-token-expire-time-millis = 2880000
|
||||
modules.oauth2-code-service.refresh-token-expire-time-millis = 43200000
|
||||
20
system/system-biz/src/main/resources/biz.yaml
Normal file
20
system/system-biz/src/main/resources/biz.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
spring:
|
||||
# 数据源配置项
|
||||
datasource:
|
||||
url: jdbc:mysql://s1.iocoder.cn:3306/mall_system?useSSL=false&useUnicode=true&characterEncoding=UTF-8
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
username: root
|
||||
password: ${MALL_MYSQL_PASSWORD}
|
||||
|
||||
# MyBatis Plus 配置项
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
|
||||
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
type-aliases-package: cn.iocoder.mall.system.biz.dataobject
|
||||
|
||||
Reference in New Issue
Block a user