add
This commit is contained in:
10
pom.xml
10
pom.xml
@ -13,6 +13,7 @@
|
||||
<module>qiaoba-apis</module>
|
||||
<module>qiaoba-commons</module>
|
||||
<module>qiaoba-application</module>
|
||||
<module>qiaoba-auth</module>
|
||||
</modules>
|
||||
|
||||
<parent>
|
||||
@ -104,6 +105,11 @@
|
||||
</dependency>
|
||||
|
||||
<!-- ======================== system module ======================== -->
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-auth</artifactId>
|
||||
<version>${qiaoba.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-base</artifactId>
|
||||
@ -136,12 +142,12 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-security</artifactId>
|
||||
<artifactId>qiaoba-common-poi</artifactId>
|
||||
<version>${qiaoba.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-poi</artifactId>
|
||||
<artifactId>qiaoba-common-redis</artifactId>
|
||||
<version>${qiaoba.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -31,7 +31,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-security</artifactId>
|
||||
<artifactId>qiaoba-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -2,12 +2,15 @@ package com.qiaoba.api.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.qiaoba.common.base.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 部门信息 sys_dept
|
||||
*
|
||||
@ -41,11 +44,14 @@ public class SysDept extends BaseEntity {
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@Size(min = 1, max = 20, message = "部门名称允许长度: {min}-{max}")
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
@Min(value = 1, message = "排序最小允许: {value}")
|
||||
@Max(value = Integer.MAX_VALUE, message = "排序最大允许: {value}")
|
||||
private Integer orderNum;
|
||||
|
||||
/**
|
||||
@ -66,6 +72,7 @@ public class SysDept extends BaseEntity {
|
||||
/**
|
||||
* 部门状态:0停用,1正常
|
||||
*/
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
}
|
||||
|
@ -4,9 +4,15 @@ import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.qiaoba.common.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 岗位信息 sys_post
|
||||
*
|
||||
@ -22,19 +28,28 @@ public class SysPost extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "岗位序号" , width = 20)
|
||||
@Excel(name = "岗位序号", width = 20)
|
||||
private String postId;
|
||||
|
||||
@Excel(name = "岗位编码" , width = 20)
|
||||
private String postCode;
|
||||
|
||||
@Excel(name = "岗位名称" , width = 20)
|
||||
@Excel(name = "岗位名称", width = 20)
|
||||
@Schema(description = "岗位名称")
|
||||
@Size(min = 1, max = 20, message = "岗位名称允许长度: {min}-{max}")
|
||||
private String postName;
|
||||
|
||||
@Excel(name = "岗位排序" , width = 20)
|
||||
private String postSort;
|
||||
@Excel(name = "岗位编码", width = 20)
|
||||
@Schema(description = "岗位编码")
|
||||
@Size(min = 1, max = 20, message = "岗位编码允许长度: {min}-{max}")
|
||||
private String postCode;
|
||||
|
||||
@Excel(name = "状态" , width = 20, replace = {"正常_1" , "异常_0"})
|
||||
@Excel(name = "岗位排序", width = 20)
|
||||
@Schema(description = "岗位排序")
|
||||
@Min(value = 1, message = "排序最小允许: {value}")
|
||||
@Max(value = Integer.MAX_VALUE, message = "排序最大允许: {value}")
|
||||
private Integer postSort;
|
||||
|
||||
@Excel(name = "状态", width = 20, replace = {"正常_1", "异常_0"})
|
||||
@Schema(description = "状态(0->禁用,1->正常)")
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.qiaoba.api.system.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户登录对象
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2021/10/15 0015 上午 10:05
|
||||
*/
|
||||
@Data
|
||||
public class LoginDto {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 唯一标识
|
||||
*/
|
||||
private String uuid = "";
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.qiaoba.api.system.entity.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ -18,6 +19,8 @@ public class SysDeptParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "部门名称")
|
||||
private String deptName;
|
||||
@Schema(description = "状态(0->禁用,1->正常)")
|
||||
private String status;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.qiaoba.api.system.entity.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ -18,10 +19,13 @@ public class SysPostParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "岗位名称")
|
||||
private String postName;
|
||||
|
||||
@Schema(description = "岗位编码")
|
||||
private String postCode;
|
||||
|
||||
@Schema(description = "状态(0->禁用,1->正常)")
|
||||
private String status;
|
||||
|
||||
public SysPostParam() {
|
||||
|
@ -45,7 +45,7 @@ public interface SysDeptApiService {
|
||||
* @param deptId 部门Id
|
||||
* @return 部门信息
|
||||
*/
|
||||
SysDept selectById(Long deptId);
|
||||
SysDept selectById(String deptId);
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
@ -53,7 +53,7 @@ public interface SysDeptApiService {
|
||||
* @param deptId 部门Id
|
||||
* @return > 0 = success
|
||||
*/
|
||||
int deleteById(Long deptId);
|
||||
int deleteById(String deptId);
|
||||
|
||||
/**
|
||||
* 构建前端部门树
|
||||
|
@ -5,6 +5,7 @@ import com.qiaoba.api.system.entity.param.SysMenuParam;
|
||||
import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 菜单对外暴露接口
|
||||
@ -54,4 +55,5 @@ public interface SysMenuApiService {
|
||||
* @return > 0 = success
|
||||
*/
|
||||
int deleteById(String menuId);
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public interface SysRoleApiService {
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids 角色ID列表
|
||||
* @return > 0 = success
|
||||
* @return > 0 = success
|
||||
*/
|
||||
int deleteByIds(List<String> ids);
|
||||
|
||||
@ -71,4 +71,5 @@ public interface SysRoleApiService {
|
||||
* @return 结果
|
||||
*/
|
||||
int authDataScope(DataScopeDto dto);
|
||||
|
||||
}
|
||||
|
@ -37,6 +37,14 @@ public interface SysUserApiService {
|
||||
*/
|
||||
SysUser selectById(String userId, Boolean hasPassword);
|
||||
|
||||
/**
|
||||
* 查询用户
|
||||
*
|
||||
* @param username 登录账号
|
||||
* @return SysUser
|
||||
*/
|
||||
SysUser selectByUsername(String username);
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
|
@ -16,8 +16,23 @@ spring:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
|
||||
qiaoba:
|
||||
auth:
|
||||
whitelist:
|
||||
- /
|
||||
- /*.*
|
||||
- /favicon.ico
|
||||
- /**/*.html
|
||||
- /**/*.css
|
||||
- /**/*.js
|
||||
- /swagger-resources
|
||||
- /v3/api-docs/**
|
||||
- /druid/**
|
||||
- /file/**
|
||||
- /login
|
||||
- /register
|
||||
- /captchaImage
|
||||
|
||||
# springdoc-openapi项目配置
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
@ -29,6 +44,7 @@ springdoc:
|
||||
- group: '系统管理'
|
||||
paths-to-match: '/**'
|
||||
packages-to-scan: com.qiaoba.module.system.controller
|
||||
|
||||
# knife4j的增强配置,不需要增强可以不配
|
||||
knife4j:
|
||||
enable: true
|
||||
|
36
qiaoba-auth/pom.xml
Normal file
36
qiaoba-auth/pom.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>qiaoba-boot</artifactId>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>qiaoba-auth</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- common-base -->
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-base</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-web</artifactId>
|
||||
</dependency>
|
||||
<!-- common-redis -->
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,96 @@
|
||||
package com.qiaoba.auth.config;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.qiaoba.auth.constants.SecurityConstant;
|
||||
import com.qiaoba.auth.filters.JwtAuthenticationTokenFilter;
|
||||
import com.qiaoba.auth.handler.AccessDeniedHandler;
|
||||
import com.qiaoba.auth.handler.LogoutHandler;
|
||||
import com.qiaoba.auth.properties.AuthConfigProperties;
|
||||
import com.qiaoba.auth.utils.TokenUtil;
|
||||
import com.qiaoba.common.redis.service.RedisService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* SpringSecurity安全配置
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/15 11:23
|
||||
*/
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Slf4j
|
||||
public class SpringSecurityConfig {
|
||||
|
||||
private final AuthConfigProperties authConfigProperties;
|
||||
private final AccessDeniedHandler accessDeniedHandler;
|
||||
private final LogoutHandler logoutHandler;
|
||||
private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
||||
private final RedisService redisService;
|
||||
|
||||
/**
|
||||
* 创建Token秘钥
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initSecret() {
|
||||
if (redisService.hasKey(SecurityConstant.REDIS_SECRET_KEY)) {
|
||||
TokenUtil.secret = SecureUtil.md5(SecureUtil.md5(redisService.get(SecurityConstant.REDIS_SECRET_KEY).toString()));
|
||||
} else {
|
||||
String random = RandomUtil.randomString(8);
|
||||
TokenUtil.secret = SecureUtil.md5(SecureUtil.md5(random));
|
||||
redisService.set(SecurityConstant.REDIS_SECRET_KEY, random);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
|
||||
//白名单
|
||||
for (String url : authConfigProperties.getWhitelist()) {
|
||||
registry.antMatchers(url).permitAll();
|
||||
}
|
||||
|
||||
// 由于使用的是JWT,我们这里不需要csrf
|
||||
httpSecurity.csrf()
|
||||
.disable()
|
||||
//添加自定义未授权和未登录结果返回
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(accessDeniedHandler)
|
||||
.and()
|
||||
// 基于token,所以不需要session
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
//跨域请求会先进行一次options请求
|
||||
.antMatchers(HttpMethod.OPTIONS)
|
||||
.permitAll()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest()
|
||||
.authenticated();
|
||||
// 禁用缓存
|
||||
httpSecurity.headers().cacheControl();
|
||||
// 退出处理
|
||||
httpSecurity.logout().logoutUrl(SecurityConstant.LOGOUT_URL).logoutSuccessHandler(logoutHandler);
|
||||
// 添加JWT filter
|
||||
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return httpSecurity.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.qiaoba.auth.constants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 安全常量
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022/9/8 0008 下午 14:54
|
||||
*/
|
||||
public class SecurityConstant {
|
||||
|
||||
public static final int MAX_ERROR_COUNT = 5;
|
||||
public static final String LOGOUT_URL = "/logout";
|
||||
public static final String HAS_BEEN_PULLED_BLACK = "您的IP已经被系统拉黑";
|
||||
public static final String ACCESS_DENIED = "暂无权限访问, 请重新登录";
|
||||
public static final String BLACKLIST_KEY = "login:blacklist";
|
||||
public static final String LOGIN_ERROR_COUNT = "login:errorCount:";
|
||||
public static final String BLACKLIST_ON = "true";
|
||||
public static final String BLACKLIST_ON_OFF_KEY = "sys_config:sys.account.blacklistOnOff";
|
||||
public static final String CAPTCHA_KEY = "login:captcha:";
|
||||
public static final String CAPTCHA_ON_OFF_KEY = "sys_config:sys.account.captchaOnOff";
|
||||
public static final String CAPTCHA_ON = "true";
|
||||
public static final String REGISTER_ON_OFF_KEY = "sys_config:sys.account.registerUser";
|
||||
public static final String REGISTER_ON = "true";
|
||||
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
|
||||
/**
|
||||
* 登录成功
|
||||
*/
|
||||
public static final String LOGIN_SUCCESS = "登录成功";
|
||||
/**
|
||||
* 登录失败
|
||||
*/
|
||||
public static final String LOGIN_FAIL = "登录失败";
|
||||
/**
|
||||
* 密码错误
|
||||
*/
|
||||
public static final String PASSWORD_ERROR = "密码错误";
|
||||
|
||||
/**
|
||||
* token header
|
||||
*/
|
||||
public static final String TOKEN_HEADER = "Authorization";
|
||||
|
||||
/**
|
||||
* token前缀
|
||||
*/
|
||||
public static final String TOKEN_HEAD = "Bearer ";
|
||||
|
||||
|
||||
/**
|
||||
* Xss过滤白名单
|
||||
*/
|
||||
public final static List<String> XSS_WHITELIST = Arrays.asList(
|
||||
"/captchaImage" ,
|
||||
"/login",
|
||||
"/workflow/process/start",
|
||||
"/workflow/model/save"
|
||||
);
|
||||
|
||||
/**
|
||||
* 需要限流的接口
|
||||
*/
|
||||
public final static List<String> LIMIT_URI = Arrays.asList(
|
||||
"/captchaImage" ,
|
||||
"/login" ,
|
||||
"/register"
|
||||
);
|
||||
|
||||
/**
|
||||
* 限流的RedisKey
|
||||
*/
|
||||
public final static String RATE_LIMIT_KEY = "rateLimit:";
|
||||
|
||||
/**
|
||||
* 同IP每秒最大允许访问次数
|
||||
*/
|
||||
public final static Integer MAX_RATE_LIMIT_TOTAL = 5;
|
||||
}
|
172
qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java
Normal file
172
qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java
Normal file
@ -0,0 +1,172 @@
|
||||
package com.qiaoba.auth.entity;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 登录用户身份权限
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2021/10/15 0015 上午 10:05
|
||||
*/
|
||||
public class LoginUser implements UserDetails {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private String deptId;
|
||||
|
||||
/**
|
||||
* 登录账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
private List<String> roleIds;
|
||||
|
||||
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
private Set<String> permissions;
|
||||
|
||||
|
||||
public LoginUser() {
|
||||
}
|
||||
|
||||
public LoginUser(String userId, String deptId, String username, String nickname, List<String> roleIds, Set<String> permissions) {
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
this.username = username;
|
||||
this.permissions = permissions;
|
||||
this.nickname = nickname;
|
||||
this.roleIds = roleIds;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getDeptId() {
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(String deptId) {
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getRoleIds() {
|
||||
return roleIds;
|
||||
}
|
||||
|
||||
public void setRoleIds(List<String> roleIds) {
|
||||
this.roleIds = roleIds;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(Set<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户是否未过期,过期无法验证
|
||||
*/
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户是否解锁,锁定的用户无法进行身份验证
|
||||
*/
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可用 ,禁用的用户不能身份验证
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
//返回当前用户的权限
|
||||
return permissions.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.qiaoba.auth.filters;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.qiaoba.auth.constants.SecurityConstant;
|
||||
import com.qiaoba.auth.properties.AuthConfigProperties;
|
||||
import com.qiaoba.auth.utils.TokenUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* JwtAuthenticationTokenFilter
|
||||
* 为了保证 SecurityContext 上下文中 userInfo 是最新的
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2021/10/21 0021 下午 14:13
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final AuthConfigProperties authConfigProperties;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain chain) throws ServletException, IOException {
|
||||
// 鉴权白名单, 放行
|
||||
if (authConfigProperties.getWhitelist().contains(request.getRequestURI())) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
// 取Header中的Token
|
||||
String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER);
|
||||
if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) {
|
||||
String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length());
|
||||
if (TokenUtil.validateToken(authToken)) {
|
||||
String username = TokenUtil.getUserNameFromToken(authToken);
|
||||
if (StrUtil.isNotBlank(username) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) {
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.qiaoba.auth.handler;
|
||||
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.qiaoba.auth.constants.SecurityConstant;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.common.web.utils.ResponseUtil;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 无权限处理器
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/15 14:14
|
||||
*/
|
||||
@Component
|
||||
public class AccessDeniedHandler implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||
AjaxResult result = AjaxResult.error(HttpStatus.HTTP_UNAUTHORIZED, SecurityConstant.ACCESS_DENIED);
|
||||
ResponseUtil.response(response, JSONUtil.toJsonStr(result));
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.qiaoba.auth.handler;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 退出处理器
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022/1/4 0004 下午 16:20
|
||||
*/
|
||||
@Component
|
||||
public class LogoutHandler implements LogoutSuccessHandler {
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) {
|
||||
//删除SecurityContext上下文中的信息
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.qiaoba.auth.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 鉴权配置(白名单/XSS)
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/15 11:09
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "qiaoba.auth")
|
||||
@Data
|
||||
@EnableConfigurationProperties
|
||||
public class AuthConfigProperties {
|
||||
|
||||
private List<String> whitelist;
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.qiaoba.auth.utils;
|
||||
|
||||
import com.qiaoba.auth.entity.LoginUser;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
/**
|
||||
* SecurityUtil
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022/8/16 0016 下午 14:51
|
||||
*/
|
||||
public class SecurityUtil {
|
||||
|
||||
private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
|
||||
|
||||
/**
|
||||
* 获取登录用户的账号
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public static String getLoginUsername() {
|
||||
return getLoginUser().getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户的账号
|
||||
*
|
||||
* @return nickname
|
||||
*/
|
||||
public static String getLoginNickname() {
|
||||
return getLoginUser().getNickname();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户的ID
|
||||
*
|
||||
* @return userId
|
||||
*/
|
||||
public static String getLoginUserId() {
|
||||
return getLoginUser().getUserId();
|
||||
}
|
||||
|
||||
|
||||
public static LoginUser getLoginUser() {
|
||||
SecurityContext ctx = SecurityContextHolder.getContext();
|
||||
Authentication auth = ctx.getAuthentication();
|
||||
return (LoginUser) auth.getPrincipal();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密密码
|
||||
*
|
||||
* @param password 原密码
|
||||
* @return 加密后密码
|
||||
*/
|
||||
public static String encryptPassword(String password) {
|
||||
return PASSWORD_ENCODER.encode(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断密码是否相同
|
||||
*
|
||||
* @param rawPassword 真实密码
|
||||
* @param encodedPassword 加密后字符
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean matchesPassword(String rawPassword, String encodedPassword) {
|
||||
return PASSWORD_ENCODER.matches(rawPassword, encodedPassword);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.qiaoba.auth.utils;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.jwt.JWTPayload;
|
||||
import cn.hutool.jwt.JWTUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TokenUtil
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022/6/8 0008 上午 11:44
|
||||
*/
|
||||
public class TokenUtil {
|
||||
|
||||
|
||||
/**
|
||||
* jwt 加解密密钥,第一次项目启动时创建随机数
|
||||
*/
|
||||
public static String secret;
|
||||
|
||||
|
||||
public static String generateToken(String username) {
|
||||
DateTime now = DateTime.now();
|
||||
// 3天过期
|
||||
DateTime newTime = now.offsetNew(DateField.HOUR, 72);
|
||||
|
||||
Map<String, Object> payload = new HashMap<String, Object>(4);
|
||||
//签发时间
|
||||
payload.put(JWTPayload.ISSUED_AT, now);
|
||||
//过期时间
|
||||
payload.put(JWTPayload.EXPIRES_AT, newTime);
|
||||
//生效时间
|
||||
payload.put(JWTPayload.NOT_BEFORE, now);
|
||||
//载荷
|
||||
payload.put(JWTPayload.SUBJECT, username);
|
||||
|
||||
return JWTUtil.createToken(payload, secret.getBytes());
|
||||
}
|
||||
|
||||
public static String getUserNameFromToken(String token) {
|
||||
try {
|
||||
return JWTUtil.parseToken(token).getPayload(JWTPayload.SUBJECT).toString();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Token是否有效
|
||||
*
|
||||
* @param token token
|
||||
* @return 是/否
|
||||
*/
|
||||
public static boolean validateToken(String token) {
|
||||
try {
|
||||
if (!JWTUtil.verify(token, secret.getBytes())) {
|
||||
return false;
|
||||
}
|
||||
long expireTime = Long.parseLong(JWTUtil.parseToken(token).getPayload(JWTPayload.EXPIRES_AT).toString() + "000");
|
||||
return new DateTime(expireTime).after(DateTime.now());
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "qiaoba.auth",
|
||||
"type": "com.qiaoba.auth.properties.AuthConfigProperties",
|
||||
"sourceType": "com.qiaoba.auth.properties.AuthConfigProperties"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "qiaoba.auth.whitelist",
|
||||
"type": "java.util.List<java.lang.String>",
|
||||
"sourceType": "com.qiaoba.auth.properties.AuthConfigProperties"
|
||||
}
|
||||
],
|
||||
"hints": []
|
||||
}
|
6
qiaoba-auth/src/main/resources/META-INF/spring.factories
Normal file
6
qiaoba-auth/src/main/resources/META-INF/spring.factories
Normal file
@ -0,0 +1,6 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.qiaoba.auth.properties.AuthConfigProperties,\
|
||||
com.qiaoba.auth.handler.AccessDeniedHandler,\
|
||||
com.qiaoba.auth.handler.LogoutHandler,\
|
||||
com.qiaoba.auth.filters.JwtAuthenticationTokenFilter,\
|
||||
com.qiaoba.auth.config.SpringSecurityConfig
|
@ -17,7 +17,6 @@
|
||||
<module>qiaoba-common-web</module>
|
||||
<module>qiaoba-common-doc</module>
|
||||
<module>qiaoba-common-redis</module>
|
||||
<module>qiaoba-common-security</module>
|
||||
<module>qiaoba-common-poi</module>
|
||||
</modules>
|
||||
|
||||
|
@ -16,5 +16,9 @@
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.qiaoba.common.database.utils;
|
||||
package com.qiaoba.common.base.utils;
|
||||
|
||||
/**
|
||||
* 租户工具类
|
@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import com.qiaoba.common.database.utils.TenantUtil;
|
||||
import com.qiaoba.common.base.utils.TenantUtil;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -1,14 +1,10 @@
|
||||
package com.qiaoba.common.database.entity;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页查询实体类
|
||||
@ -31,16 +27,6 @@ public class PageQuery implements Serializable {
|
||||
*/
|
||||
private Integer pageNum;
|
||||
|
||||
/**
|
||||
* 排序列
|
||||
*/
|
||||
private String orderByColumn;
|
||||
|
||||
/**
|
||||
* 排序的方向desc或者asc
|
||||
*/
|
||||
private String isAsc;
|
||||
|
||||
/**
|
||||
* 当前记录起始索引 默认值
|
||||
*/
|
||||
@ -57,12 +43,7 @@ public class PageQuery implements Serializable {
|
||||
if (pageNum <= 0) {
|
||||
pageNum = DEFAULT_PAGE_NUM;
|
||||
}
|
||||
Page<T> page = new Page<>(pageNum, pageSize);
|
||||
/* List<OrderItem> orderItems = buildOrderItem();
|
||||
if (CollUtil.isNotEmpty(orderItems)) {
|
||||
page.addOrder(orderItems);
|
||||
}*/
|
||||
return page;
|
||||
return new Page<>(pageNum, pageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,14 +2,13 @@ package com.qiaoba.common.database.filters;
|
||||
|
||||
import com.qiaoba.common.database.config.DynamicDataSourceContext;
|
||||
import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
|
||||
import com.qiaoba.common.database.utils.TenantUtil;
|
||||
import com.qiaoba.common.base.utils.TenantUtil;
|
||||
import com.qiaoba.common.web.utils.ResponseUtil;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.qiaoba.common.database.factories.DynamicDataSourceFactory,\
|
||||
com.qiaoba.common.database.config.MybatisPlusConfig
|
||||
|
||||
|
||||
|
@ -17,10 +17,14 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-base</artifactId>
|
||||
</dependency>
|
||||
<!-- Jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -1,8 +1,9 @@
|
||||
package com.qiaoba.common.redis.service.impl;
|
||||
|
||||
|
||||
import com.qiaoba.common.base.utils.TenantUtil;
|
||||
import com.qiaoba.common.redis.service.RedisService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -20,33 +21,34 @@ import java.util.concurrent.TimeUnit;
|
||||
* @since 2021/10/2 0003 下午 17:44
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RedisServiceImpl implements RedisService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public void set(String key, Object value, long time) {
|
||||
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
||||
redisTemplate.opsForValue().set(handleKey(key), value, time, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String key, Object value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
redisTemplate.opsForValue().set(handleKey(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String key) {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
return redisTemplate.opsForValue().get(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean del(String key) {
|
||||
return redisTemplate.delete(key);
|
||||
return redisTemplate.delete(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void del(Collection<String> collection) {
|
||||
// todo
|
||||
redisTemplate.delete(collection);
|
||||
}
|
||||
|
||||
@ -57,168 +59,178 @@ public class RedisServiceImpl implements RedisService {
|
||||
|
||||
@Override
|
||||
public Long getExpire(String key) {
|
||||
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
|
||||
return redisTemplate.getExpire(handleKey(key), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hasKey(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
return redisTemplate.hasKey(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long incr(String key, long delta) {
|
||||
return redisTemplate.opsForValue().increment(key, delta);
|
||||
return redisTemplate.opsForValue().increment(handleKey(key), delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decr(String key, long delta) {
|
||||
return redisTemplate.opsForValue().increment(key, -delta);
|
||||
return redisTemplate.opsForValue().increment(handleKey(key), -delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object hGet(String key, String hashKey) {
|
||||
return redisTemplate.opsForHash().get(key, hashKey);
|
||||
return redisTemplate.opsForHash().get(handleKey(key), hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hSet(String key, String hashKey, Object value, long time) {
|
||||
redisTemplate.opsForHash().put(key, hashKey, value);
|
||||
return expire(key, time);
|
||||
String newKey = handleKey(key);
|
||||
redisTemplate.opsForHash().put(newKey, hashKey, value);
|
||||
return expire(newKey, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hSet(String key, String hashKey, Object value) {
|
||||
redisTemplate.opsForHash().put(key, hashKey, value);
|
||||
redisTemplate.opsForHash().put(handleKey(key), hashKey, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> hGetAll(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
return redisTemplate.opsForHash().entries(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hSetAll(String key, Map<String, Object> map, long time) {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
return expire(key, time);
|
||||
String newKey = handleKey(key);
|
||||
redisTemplate.opsForHash().putAll(newKey, map);
|
||||
return expire(newKey, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hSetAll(String key, Map<String, ?> map) {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
redisTemplate.opsForHash().putAll(handleKey(key), map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hDel(String key, Object... hashKey) {
|
||||
redisTemplate.opsForHash().delete(key, hashKey);
|
||||
redisTemplate.opsForHash().delete(handleKey(key), hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hHasKey(String key, String hashKey) {
|
||||
return redisTemplate.opsForHash().hasKey(key, hashKey);
|
||||
return redisTemplate.opsForHash().hasKey(handleKey(key), hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long hIncr(String key, String hashKey, Long delta) {
|
||||
return redisTemplate.opsForHash().increment(key, hashKey, delta);
|
||||
return redisTemplate.opsForHash().increment(handleKey(key), hashKey, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long hDecr(String key, String hashKey, Long delta) {
|
||||
return redisTemplate.opsForHash().increment(key, hashKey, -delta);
|
||||
return redisTemplate.opsForHash().increment(handleKey(key), hashKey, -delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Object> sMembers(String key) {
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
return redisTemplate.opsForSet().members(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sAdd(String key, Object... values) {
|
||||
return redisTemplate.opsForSet().add(key, values);
|
||||
return redisTemplate.opsForSet().add(handleKey(key), values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sAdd(String key, long time, Object... values) {
|
||||
Long count = redisTemplate.opsForSet().add(key, values);
|
||||
expire(key, time);
|
||||
String newKey = handleKey(key);
|
||||
Long count = redisTemplate.opsForSet().add(newKey, values);
|
||||
expire(newKey, time);
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean sIsMember(String key, Object value) {
|
||||
return redisTemplate.opsForSet().isMember(key, value);
|
||||
return redisTemplate.opsForSet().isMember(handleKey(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sSize(String key) {
|
||||
return redisTemplate.opsForSet().size(key);
|
||||
return redisTemplate.opsForSet().size(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sRemove(String key, Object... values) {
|
||||
return redisTemplate.opsForSet().remove(key, values);
|
||||
return redisTemplate.opsForSet().remove(handleKey(key), values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> lRange(String key, long start, long end) {
|
||||
return redisTemplate.opsForList().range(key, start, end);
|
||||
return redisTemplate.opsForList().range(handleKey(key), start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lSize(String key) {
|
||||
return redisTemplate.opsForList().size(key);
|
||||
return redisTemplate.opsForList().size(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lIndex(String key, long index) {
|
||||
return redisTemplate.opsForList().index(key, index);
|
||||
return redisTemplate.opsForList().index(handleKey(key), index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lPush(String key, Object value) {
|
||||
return redisTemplate.opsForList().rightPush(key, value);
|
||||
return redisTemplate.opsForList().rightPush(handleKey(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lPush(String key, Object value, long time) {
|
||||
Long index = redisTemplate.opsForList().rightPush(key, value);
|
||||
expire(key, time);
|
||||
String newKey = handleKey(key);
|
||||
Long index = redisTemplate.opsForList().rightPush(newKey, value);
|
||||
expire(newKey, time);
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lPushAll(String key, Object... values) {
|
||||
return redisTemplate.opsForList().rightPushAll(key, values);
|
||||
return redisTemplate.opsForList().rightPushAll(handleKey(key), values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lPushAll(String key, Long time, Object... values) {
|
||||
Long count = redisTemplate.opsForList().rightPushAll(key, values);
|
||||
expire(key, time);
|
||||
String newKey = handleKey(key);
|
||||
Long count = redisTemplate.opsForList().rightPushAll(newKey, values);
|
||||
expire(newKey, time);
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long lRemove(String key, long count, Object value) {
|
||||
return redisTemplate.opsForList().remove(key, count, value);
|
||||
return redisTemplate.opsForList().remove(handleKey(key), count, value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<String> getKeys(String key) {
|
||||
return redisTemplate.keys(key);
|
||||
return redisTemplate.keys(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getObject(String key, Class<T> clazz) {
|
||||
return (T) get(key);
|
||||
return (T) get(handleKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> getObjectList(String key, Class<T> clazz) {
|
||||
return (List<T>) get(key);
|
||||
return (List<T>) get(handleKey(key));
|
||||
}
|
||||
|
||||
private String handleKey(String key) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("tenant_").append(TenantUtil.getTenantId()).append(":").append(key);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>qiaoba-commons</artifactId>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>qiaoba-common-security</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,30 +0,0 @@
|
||||
package com.qiaoba.common.security.utils;
|
||||
|
||||
/**
|
||||
* SecurityUtil
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/9 9:22
|
||||
*/
|
||||
public class SecurityUtil {
|
||||
|
||||
/**
|
||||
* 获取登录用户的账号
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public static String getLoginUsername() {
|
||||
return "admin";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户的ID
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public static String getLoginUserId() {
|
||||
return "1L";
|
||||
}
|
||||
|
||||
}
|
@ -3,10 +3,14 @@ package com.qiaoba.common.web.advice;
|
||||
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*
|
||||
@ -38,8 +42,31 @@ public class ExceptionAdvice {
|
||||
*/
|
||||
@ExceptionHandler(ServiceException.class)
|
||||
@ResponseBody
|
||||
public AjaxResult handlerApiException(ServiceException e) {
|
||||
public AjaxResult handlerServiceException(ServiceException e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验
|
||||
*
|
||||
* @param e MethodArgumentNotValidException
|
||||
* @return AjaxResult
|
||||
*/
|
||||
@ExceptionHandler({MethodArgumentNotValidException.class})
|
||||
@ResponseBody
|
||||
public AjaxResult handlerValidException(MethodArgumentNotValidException e) {
|
||||
return AjaxResult.error(Objects.isNull(e.getBindingResult().getFieldError()) ? e.getMessage() : e.getBindingResult().getFieldError().getDefaultMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验
|
||||
*
|
||||
* @param e BindException
|
||||
* @return AjaxResult
|
||||
*/
|
||||
@ExceptionHandler({BindException.class})
|
||||
@ResponseBody
|
||||
public AjaxResult handlerValidException(BindException e) {
|
||||
return AjaxResult.error(Objects.isNull(e.getBindingResult().getFieldError()) ? e.getMessage() : e.getBindingResult().getFieldError().getDefaultMessage());
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ import com.qiaoba.api.system.entity.SysDept;
|
||||
import com.qiaoba.api.system.entity.param.SysDeptParam;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.module.system.service.SysDeptService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -19,50 +22,58 @@ import java.util.List;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/system/dept")
|
||||
@Tag(name = "部门管理")
|
||||
@RequiredArgsConstructor
|
||||
public class SysDeptController {
|
||||
|
||||
private final SysDeptService sysDeptService;
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:list')")
|
||||
@PreAuthorize("hasAuthority('system:dept:list')")
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获取列表")
|
||||
public AjaxResult list(SysDeptParam param) {
|
||||
return AjaxResult.success(sysDeptService.selectList(param));
|
||||
}
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:list')")
|
||||
@PreAuthorize("hasAuthority('system:dept:list')")
|
||||
@GetMapping("/list/exclude/{deptId}")
|
||||
@Operation(summary = "查询部门列表(排除节点)")
|
||||
public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) String deptId) {
|
||||
return AjaxResult.success(sysDeptService.excludeChild(deptId));
|
||||
}
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:query')")
|
||||
@PreAuthorize("hasAuthority('system:dept:query')")
|
||||
@GetMapping(value = "/{deptId}")
|
||||
public AjaxResult getInfo(@PathVariable Long deptId) {
|
||||
@Operation(summary = "获取详情")
|
||||
public AjaxResult getInfo(@PathVariable String deptId) {
|
||||
return AjaxResult.success(sysDeptService.selectById(deptId));
|
||||
}
|
||||
|
||||
@GetMapping("/deptTree")
|
||||
@Operation(summary = "构建部门树")
|
||||
public AjaxResult deptTree(SysDeptParam param) {
|
||||
List<SysDept> list = sysDeptService.selectList(param);
|
||||
return AjaxResult.success(sysDeptService.buildDeptTree(list));
|
||||
}
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:add')")
|
||||
@PreAuthorize("hasAuthority('system:dept:add')")
|
||||
@PostMapping
|
||||
@Operation(summary = "新增部门")
|
||||
public AjaxResult add(@Validated @RequestBody SysDept dept) {
|
||||
return AjaxResult.toAjax(sysDeptService.insert(dept));
|
||||
}
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:edit')")
|
||||
@PreAuthorize("hasAuthority('system:dept:edit')")
|
||||
@PutMapping
|
||||
@Operation(summary = "修改部门")
|
||||
public AjaxResult edit(@Validated @RequestBody SysDept dept) {
|
||||
return AjaxResult.toAjax(sysDeptService.updateById(dept));
|
||||
}
|
||||
|
||||
//@PreAuthorize("hasAuthority('system:dept:remove')")
|
||||
@PreAuthorize("hasAuthority('system:dept:remove')")
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable Long id) {
|
||||
@Operation(summary = "删除部门")
|
||||
public AjaxResult remove(@PathVariable String id) {
|
||||
return AjaxResult.toAjax(sysDeptService.deleteById(id));
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
package com.qiaoba.module.system.controller;
|
||||
|
||||
import com.qiaoba.api.system.entity.SysMenu;
|
||||
import com.qiaoba.api.system.entity.dto.LoginDto;
|
||||
import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.module.system.service.SysLoginService;
|
||||
import com.qiaoba.module.system.service.SysMenuService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* 登录 Web层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
@ -23,15 +27,30 @@ import java.util.List;
|
||||
public class SysLoginController {
|
||||
|
||||
private final SysMenuService sysMenuService;
|
||||
private final SysLoginService sysLoginService;
|
||||
|
||||
|
||||
@GetMapping("/captchaImage")
|
||||
public AjaxResult getCaptchaImage() {
|
||||
return sysLoginService.getCaptchaImage();
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public String login() {
|
||||
return "{\"msg\":\"操作成功\",\"code\":200,\"token\":\"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhhNjY4MGY1LTI0OTAtNDUyYi1hYzQ1LWE5YWI0MzQ0YTRlYyJ9.mTZr7TN1Jk2-_7zbeUbOBuHijVLiqY2QSbhcAIfWuX4oF22xGw_DpxOz3I2_-TLeYlJN4y2Gm1qmw6ricqCBqw\"}";
|
||||
public AjaxResult login(@RequestBody LoginDto dto) {
|
||||
String token = sysLoginService.login(dto);
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("token", token);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@GetMapping("/getInfo")
|
||||
public String getInfo() {
|
||||
List<String> roleIds = SecurityUtil.getLoginUser().getRoleIds();
|
||||
Set<String> permissions = SecurityUtil.getLoginUser().getPermissions();
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("permissions", permissions);
|
||||
ajax.put("roles", roleIds);
|
||||
ajax.put("user",sysLoginService.selectUserFromCache(SecurityUtil.getLoginUserId()));
|
||||
return "{\"msg\":\"操作成功\",\"code\":200,\"permissions\":[\"*:*:*\"],\"roles\":[\"admin\"],\"user\":{\"createBy\":\"admin\",\"createTime\":\"2023-04-23 16:11:38\",\"updateBy\":null,\"updateTime\":null,\"remark\":\"管理员\",\"userId\":1,\"deptId\":103,\"userName\":\"admin\",\"nickName\":\"若依\",\"email\":\"ry@163.com\",\"phonenumber\":\"15888888888\",\"sex\":\"1\",\"avatar\":\"\",\"password\":\"$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2\",\"status\":\"0\",\"delFlag\":\"0\",\"loginIp\":\"27.154.23.192\",\"loginDate\":\"2023-05-05T09:45:24.000+08:00\",\"dept\":{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"deptId\":103,\"parentId\":101,\"ancestors\":\"0,100,101\",\"deptName\":\"研发部门\",\"orderNum\":1,\"leader\":\"若依\",\"phone\":null,\"email\":null,\"status\":\"0\",\"delFlag\":null,\"parentName\":null,\"children\":[]},\"roles\":[{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"roleId\":1,\"roleName\":\"超级管理员\",\"roleKey\":\"admin\",\"roleSort\":1,\"dataScope\":\"1\",\"menuCheckStrictly\":false,\"deptCheckStrictly\":false,\"status\":\"0\",\"delFlag\":null,\"flag\":false,\"menuIds\":null,\"deptIds\":null,\"permissions\":null,\"admin\":true}],\"roleIds\":null,\"postIds\":null,\"roleId\":null,\"admin\":true}}";
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,11 @@ import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.common.poi.utils.ExcelUtil;
|
||||
import com.qiaoba.module.system.service.SysPostService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -23,68 +27,52 @@ import java.util.List;
|
||||
@RestController
|
||||
@RequestMapping("/system/post")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "岗位管理")
|
||||
public class SysPostController {
|
||||
|
||||
private final SysPostService sysPostService;
|
||||
|
||||
/**
|
||||
* 获取岗位列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
//@PreAuthorize("hasAuthority('system:post:list')")
|
||||
@PreAuthorize("hasAuthority('system:post:list')")
|
||||
@Operation(summary = "获取列表")
|
||||
public TableDataInfo<SysPost> list(SysPostParam param, PageQuery pageQuery) {
|
||||
return sysPostService.selectPageList(param, pageQuery);
|
||||
}
|
||||
|
||||
@PostMapping("/export")
|
||||
//@PreAuthorize("hasAuthority('system:post:export')")
|
||||
@PreAuthorize("hasAuthority('system:post:export')")
|
||||
@Operation(summary = "导出岗位")
|
||||
public void export(HttpServletResponse response, SysPostParam param) {
|
||||
List<SysPost> list = sysPostService.selectList(param);
|
||||
ExcelUtil.exportExcel(list, SysPost.class, "岗位数据", response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据岗位编号获取详细信息
|
||||
*/
|
||||
@GetMapping(value = "/{postId}")
|
||||
//@PreAuthorize("hasAuthority('system:post:query')")
|
||||
@PreAuthorize("hasAuthority('system:post:query')")
|
||||
@Operation(summary = "获取详情")
|
||||
public AjaxResult getInfo(@PathVariable("postId") String postId) {
|
||||
return AjaxResult.success(sysPostService.selectById(postId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增岗位
|
||||
*/
|
||||
@PostMapping
|
||||
//@PreAuthorize("hasAuthority('system:post:add')")
|
||||
public AjaxResult add(@RequestBody SysPost post) {
|
||||
@PreAuthorize("hasAuthority('system:post:add')")
|
||||
@Operation(summary = "新增岗位")
|
||||
public AjaxResult add(@Validated @RequestBody SysPost post) {
|
||||
return AjaxResult.toAjax(sysPostService.insert(post));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改岗位
|
||||
*/
|
||||
@PutMapping
|
||||
//@PreAuthorize("hasAuthority('system:post:edit')")
|
||||
public AjaxResult edit(@RequestBody SysPost post) {
|
||||
@PreAuthorize("hasAuthority('system:post:edit')")
|
||||
@Operation(summary = "修改岗位")
|
||||
public AjaxResult edit(@Validated @RequestBody SysPost post) {
|
||||
return AjaxResult.toAjax(sysPostService.updateById(post));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除岗位
|
||||
*/
|
||||
@DeleteMapping("/{ids}")
|
||||
//@PreAuthorize("hasAuthority('system:post:remove')")
|
||||
@PreAuthorize("hasAuthority('system:post:remove')")
|
||||
@Operation(summary = "删除岗位")
|
||||
public AjaxResult remove(@PathVariable List<String> ids) {
|
||||
return AjaxResult.toAjax(sysPostService.deleteByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取岗位选择框列表
|
||||
*/
|
||||
/* @GetMapping("/optionSelect")
|
||||
public AjaxResult optionSelect() {
|
||||
List<SysPost> posts = postService.selectPostAll();
|
||||
return AjaxResult.success(posts);
|
||||
}*/
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class SysUserController {
|
||||
SysUser sysUser = sysUserService.selectById(userId, false);
|
||||
ajax.put(AjaxResult.DATA_TAG, sysUser);
|
||||
ajax.put("postIds", sysUserPostService.selectPostIdsByUserId(userId));
|
||||
ajax.put("roleIds", sysUserRoleService.selectRoleIdsByUserId(userId));
|
||||
ajax.put("roleIds", sysUserRoleService.selectRoleIdsByUserId(userId, null));
|
||||
}
|
||||
return ajax;
|
||||
}
|
||||
@ -111,7 +111,7 @@ public class SysUserController {
|
||||
List<SysRole> roles = sysRoleService.selectList(new SysRoleParam());
|
||||
ajax.put("user", user);
|
||||
ajax.put("roles", roles);
|
||||
ajax.put("hasRoleIds", sysUserRoleService.selectRoleIdsByUserId(userId));
|
||||
ajax.put("hasRoleIds", sysUserRoleService.selectRoleIdsByUserId(userId, null));
|
||||
return ajax;
|
||||
}
|
||||
|
||||
|
@ -30,4 +30,20 @@ public interface SysDeptMapper extends BaseMapper<SysDept> {
|
||||
*/
|
||||
List<String> selectDeptIdsByRoleId(String roleId);
|
||||
|
||||
/**
|
||||
* 检查是否存在子部门
|
||||
*
|
||||
* @param deptId deptId
|
||||
* @return != null -> 是
|
||||
*/
|
||||
String existChild(String deptId);
|
||||
|
||||
/**
|
||||
* 检查部门是否被使用
|
||||
*
|
||||
* @param deptId deptId
|
||||
* @return != null -> 是
|
||||
*/
|
||||
String existUsed(String deptId);
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.common.database.mapper.BaseMapperPlus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 菜单管理 数据层
|
||||
@ -38,4 +39,12 @@ public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, Sy
|
||||
* @return list
|
||||
*/
|
||||
List<SysMenuVo> selectByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 查询用户拥有的权限列表
|
||||
*
|
||||
* @param userId userId
|
||||
* @return 权限列表
|
||||
*/
|
||||
Set<String> selectPermsByUserId(String userId);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public interface SysPostMapper extends BaseMapper<SysPost> {
|
||||
* @param sysPost 岗位名称
|
||||
* @return 结果
|
||||
*/
|
||||
int checkPostNameUnique(SysPost sysPost);
|
||||
String checkPostNameUnique(SysPost sysPost);
|
||||
|
||||
/**
|
||||
* 校验岗位编码
|
||||
@ -26,6 +26,6 @@ public interface SysPostMapper extends BaseMapper<SysPost> {
|
||||
* @param sysPost 岗位编码
|
||||
* @return 结果
|
||||
*/
|
||||
int checkPostCodeUnique(SysPost sysPost);
|
||||
String checkPostCodeUnique(SysPost sysPost);
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.qiaoba.module.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.qiaoba.api.system.entity.SysUserPost;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -20,4 +21,12 @@ public interface SysUserPostMapper extends BaseMapper<SysUserPost> {
|
||||
* @return postIds
|
||||
*/
|
||||
List<String> selectPostIdsByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 查询正在被使用的岗位名称列表
|
||||
*
|
||||
* @param postIds postIds
|
||||
* @return postNames
|
||||
*/
|
||||
List<String> selectUsedPostNameByIds(@Param("list") List<String> postIds);
|
||||
}
|
||||
|
@ -19,9 +19,10 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
|
||||
* 通过userId查询所绑定的角色ID列表
|
||||
*
|
||||
* @param userId userId
|
||||
* @param status 状态
|
||||
* @return roleIds
|
||||
*/
|
||||
List<String> selectRoleIdsByUserId(String userId);
|
||||
List<String> selectRoleIdsByUserId(@Param("userId") String userId, @Param("status") String status);
|
||||
|
||||
/**
|
||||
* 批量取消角色所绑定的用户
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.qiaoba.module.system.service;
|
||||
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.api.system.entity.dto.LoginDto;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
|
||||
/**
|
||||
* 登录 服务层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/15 15:31
|
||||
*/
|
||||
public interface SysLoginService {
|
||||
|
||||
/**
|
||||
* 生成图片验证码
|
||||
*
|
||||
* @return uuid + base64
|
||||
*/
|
||||
AjaxResult getCaptchaImage();
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param dto dto
|
||||
* @return token
|
||||
*/
|
||||
String login(LoginDto dto);
|
||||
|
||||
/**
|
||||
* 从缓存中读取user
|
||||
*
|
||||
* @param userId userId
|
||||
* @return SysUser
|
||||
*/
|
||||
SysUser selectUserFromCache(String userId);
|
||||
}
|
@ -7,6 +7,7 @@ import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.api.system.service.SysMenuApiService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 菜单管理 服务层
|
||||
@ -41,6 +42,14 @@ public interface SysMenuService extends SysMenuApiService {
|
||||
*/
|
||||
List<SysMenuVo> selectByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 查询用户拥有的权限列表
|
||||
*
|
||||
* @param userId userId
|
||||
* @return 权限列表
|
||||
*/
|
||||
Set<String> selectPermsByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 菜单转路由
|
||||
*
|
||||
|
@ -34,4 +34,12 @@ public interface SysUserPostService {
|
||||
* @return postIds
|
||||
*/
|
||||
List<String> selectPostIdsByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 查询正在被使用的岗位名称列表
|
||||
*
|
||||
* @param postIds postIds
|
||||
* @return postNames
|
||||
*/
|
||||
List<String> selectUsedPostNameByIds(List<String> postIds);
|
||||
}
|
||||
|
@ -39,9 +39,10 @@ public interface SysUserRoleService {
|
||||
* 通过userId查询所绑定的角色ID列表
|
||||
*
|
||||
* @param userId userId
|
||||
* @param status 状态
|
||||
* @return roleIds
|
||||
*/
|
||||
List<String> selectRoleIdsByUserId(String userId);
|
||||
List<String> selectRoleIdsByUserId(String userId, String status);
|
||||
|
||||
/**
|
||||
* 批量选择用户授权
|
||||
|
@ -62,4 +62,5 @@ public interface SysUserService extends SysUserApiService {
|
||||
* @return list
|
||||
*/
|
||||
TableDataInfo selectUnAllocatedList(SysUserParam param, PageQuery pageQuery);
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.qiaoba.api.system.entity.SysDept;
|
||||
import com.qiaoba.api.system.entity.param.SysDeptParam;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.common.base.constants.BaseConstant;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.security.utils.SecurityUtil;
|
||||
import com.qiaoba.module.system.mapper.SysDeptMapper;
|
||||
import com.qiaoba.module.system.service.SysDeptService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -36,6 +36,7 @@ public class SysDeptServiceImpl implements SysDeptService {
|
||||
|
||||
private final SysDeptMapper sysDeptMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public int insert(SysDept sysDept) {
|
||||
if (checkDeptNameNotUnique(sysDept)) {
|
||||
@ -83,12 +84,19 @@ public class SysDeptServiceImpl implements SysDeptService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysDept selectById(Long deptId) {
|
||||
public SysDept selectById(String deptId) {
|
||||
return sysDeptMapper.selectById(deptId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteById(Long deptId) {
|
||||
public int deleteById(String deptId) {
|
||||
if (StrUtil.isNotBlank(sysDeptMapper.existChild(deptId))) {
|
||||
throw new ServiceException("存在子级部门,不允许删除");
|
||||
}
|
||||
String nickname = sysDeptMapper.existUsed(deptId);
|
||||
if (StrUtil.isNotBlank(nickname)) {
|
||||
throw new ServiceException(StrUtil.format("用户[{}]已绑定部门,不允许删除", nickname));
|
||||
}
|
||||
return sysDeptMapper.deleteById(deptId);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,146 @@
|
||||
package com.qiaoba.module.system.service.impl;
|
||||
|
||||
import cn.hutool.captcha.CaptchaUtil;
|
||||
import cn.hutool.captcha.LineCaptcha;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.api.system.entity.dto.LoginDto;
|
||||
import com.qiaoba.auth.constants.SecurityConstant;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.auth.utils.TokenUtil;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.common.redis.service.RedisService;
|
||||
import com.qiaoba.module.system.service.SysLoginService;
|
||||
import com.qiaoba.module.system.service.SysUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 登录 服务层实现
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/5/15 15:31
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysLoginServiceImpl implements SysLoginService {
|
||||
|
||||
private final RedisService redisService;
|
||||
private final HttpServletRequest request;
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final SysUserService sysUserService;
|
||||
|
||||
@Override
|
||||
public AjaxResult getCaptchaImage() {
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("register", getRegisterConfig());
|
||||
if (!getCaptchaConfig()) {
|
||||
ajax.put("captchaEnabled", false);
|
||||
return ajax;
|
||||
}
|
||||
String uuid = UUID.randomUUID().toString(true);
|
||||
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(150, 50, 4, 20);
|
||||
ajax.put("uuid", uuid);
|
||||
ajax.put("img", captcha.getImageBase64());
|
||||
redisService.set(SecurityConstant.CAPTCHA_KEY + uuid, captcha.getCode(), 120);
|
||||
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String login(LoginDto dto) {
|
||||
// 校验验证码
|
||||
validateCaptcha(dto.getCode(), dto.getUuid());
|
||||
// username查询用户信息
|
||||
SysUser sysUser = sysUserService.selectByUsername(dto.getUsername());
|
||||
// 检查账号信息
|
||||
validateUser(dto.getUsername(), sysUser);
|
||||
// 检验密码
|
||||
validatePassword(dto.getUsername(), sysUser.getPassword(), dto.getPassword());
|
||||
// 缓存user
|
||||
addUserToCache(sysUser);
|
||||
// 创建UserDetails
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(dto.getUsername());
|
||||
// 生成Token
|
||||
return TokenUtil.generateToken(userDetails.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysUser selectUserFromCache(String userId) {
|
||||
return redisService.getObject(userId, SysUser.class);
|
||||
}
|
||||
|
||||
private void addUserToCache(SysUser sysUser) {
|
||||
sysUser.setPassword(null);
|
||||
redisService.set(sysUser.getUserId(), sysUser);
|
||||
}
|
||||
|
||||
private void validatePassword(String username, String password, String inputPassword) {
|
||||
boolean result = SecurityUtil.matchesPassword(inputPassword, password);
|
||||
if (!result) {
|
||||
beforePasswordError(username);
|
||||
throw new ServiceException(SecurityConstant.PASSWORD_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void beforePasswordError(String username) {
|
||||
|
||||
}
|
||||
|
||||
private void validateUser(String username, SysUser user) {
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
throw new ServiceException(StrUtil.format("登录用户:{} 不存在", username));
|
||||
} else if (BaseEnum.YES.getCode().equals(user.getIsDelete())) {
|
||||
throw new ServiceException(StrUtil.format("对不起, 您的账号:{} 已被删除", username));
|
||||
} else if (BaseEnum.ABNORMAL.getCode().equals(user.getStatus())) {
|
||||
throw new ServiceException(StrUtil.format("对不起, 您的账号:{} 已被禁用", username));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getCaptchaConfig() {
|
||||
return false;
|
||||
/* try {
|
||||
return SecurityConstant.CAPTCHA_ON.equals(redisService.get(SecurityConstant.CAPTCHA_ON_OFF_KEY));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("Redis中验证码配置不存在!");
|
||||
}*/
|
||||
}
|
||||
|
||||
private boolean getRegisterConfig() {
|
||||
return false;
|
||||
/* try {
|
||||
return SecurityConstant.REGISTER_ON.equals(redisService.get(SecurityConstant.REGISTER_ON_OFF_KEY));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("Redis中注册配置不存在!");
|
||||
}*/
|
||||
}
|
||||
|
||||
private void validateCaptcha(String code, String uuid) {
|
||||
if (getCaptchaConfig()) {
|
||||
if (StrUtil.isBlank(code) || StrUtil.isBlank(uuid)) {
|
||||
throw new ServiceException("验证码或uuid获取失败!");
|
||||
}
|
||||
try {
|
||||
if (!redisService.hasKey(SecurityConstant.CAPTCHA_KEY + uuid)) {
|
||||
throw new ServiceException("验证码已经过期失效!");
|
||||
} else {
|
||||
if (!code.equalsIgnoreCase(redisService.get(SecurityConstant.CAPTCHA_KEY + uuid).toString())) {
|
||||
throw new ServiceException("验证码输入错误!");
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
redisService.del(SecurityConstant.CAPTCHA_KEY + uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 菜单管理 服务层实现
|
||||
@ -94,6 +95,11 @@ public class SysMenuServiceImpl implements SysMenuService {
|
||||
return sysMenuMapper.selectByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> selectPermsByUserId(String userId) {
|
||||
return sysMenuMapper.selectPermsByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RouterVo> menusToRouters(List<SysMenuVo> menus) {
|
||||
return MenuUtil.menusToRouters(menus);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.qiaoba.module.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.qiaoba.api.system.entity.SysPost;
|
||||
@ -7,9 +8,10 @@ import com.qiaoba.api.system.entity.param.SysPostParam;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.common.security.utils.SecurityUtil;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.module.system.mapper.SysPostMapper;
|
||||
import com.qiaoba.module.system.service.SysPostService;
|
||||
import com.qiaoba.module.system.service.SysUserPostService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -28,6 +30,7 @@ import java.util.List;
|
||||
public class SysPostServiceImpl implements SysPostService {
|
||||
|
||||
private final SysPostMapper sysPostMapper;
|
||||
private final SysUserPostService sysUserPostService;
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysPost> selectPageList(SysPostParam param, PageQuery pageQuery) {
|
||||
@ -64,11 +67,13 @@ public class SysPostServiceImpl implements SysPostService {
|
||||
|
||||
@Override
|
||||
public int deleteById(String deptId) {
|
||||
checkAllowDelete(CollUtil.toList(deptId));
|
||||
return sysPostMapper.deleteById(deptId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteByIds(List<String> ids) {
|
||||
checkAllowDelete(ids);
|
||||
return sysPostMapper.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
@ -88,8 +93,8 @@ public class SysPostServiceImpl implements SysPostService {
|
||||
* @param post 岗位信息
|
||||
*/
|
||||
private void checkPostNameUnique(SysPost post) {
|
||||
if (sysPostMapper.checkPostNameUnique(post) > 0) {
|
||||
throw new ServiceException(StrUtil.format("处理岗位'{}'失败,岗位名称已存在", post.getPostName()));
|
||||
if (StrUtil.isNotBlank(sysPostMapper.checkPostNameUnique(post))) {
|
||||
throw new ServiceException(StrUtil.format("处理岗位{}失败, 岗位名称已存在", post.getPostName()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +104,20 @@ public class SysPostServiceImpl implements SysPostService {
|
||||
* @param post 岗位信息
|
||||
*/
|
||||
private void checkPostCodeUnique(SysPost post) {
|
||||
if (sysPostMapper.checkPostCodeUnique(post) > 0) {
|
||||
throw new ServiceException(StrUtil.format("处理岗位'{}'失败,岗位编码已存在", post.getPostName()));
|
||||
if (StrUtil.isNotBlank(sysPostMapper.checkPostCodeUnique(post))) {
|
||||
throw new ServiceException(StrUtil.format("处理岗位{}失败, 岗位编码已存在", post.getPostName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查岗位是否允许删除
|
||||
*
|
||||
* @param ids ids
|
||||
*/
|
||||
private void checkAllowDelete(List<String> ids) {
|
||||
List<String> names = sysUserPostService.selectUsedPostNameByIds(ids);
|
||||
if (CollUtil.isNotEmpty(names)) {
|
||||
throw new ServiceException(StrUtil.format("删除岗位{}失败, 岗位已绑定用户", names.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import com.qiaoba.api.system.entity.param.SysRoleParam;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.common.security.utils.SecurityUtil;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.module.system.mapper.SysRoleMapper;
|
||||
import com.qiaoba.module.system.service.SysRoleDeptService;
|
||||
import com.qiaoba.module.system.service.SysRoleMenuService;
|
||||
@ -105,6 +105,7 @@ public class SysRoleServiceImpl implements SysRoleService {
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
private QueryWrapper<SysRole> param2Wrapper(SysRoleParam param) {
|
||||
QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
|
@ -0,0 +1,48 @@
|
||||
package com.qiaoba.module.system.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.auth.entity.LoginUser;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.module.system.service.SysMenuService;
|
||||
import com.qiaoba.module.system.service.SysUserRoleService;
|
||||
import com.qiaoba.module.system.service.SysUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户权限验证处理
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final SysUserService sysUserService;
|
||||
private final SysMenuService sysMenuService;
|
||||
private final SysUserRoleService sysUserRoleService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
SysUser user = sysUserService.selectByUsername(username);
|
||||
StrUtil.format("{}",1);
|
||||
return createUserDetails(user);
|
||||
}
|
||||
|
||||
|
||||
private UserDetails createUserDetails(SysUser user) {
|
||||
Set<String> perms = sysMenuService.selectPermsByUserId(user.getUserId());
|
||||
List<String> roleIds = sysUserRoleService.selectRoleIdsByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
|
||||
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roleIds, perms);
|
||||
}
|
||||
|
||||
}
|
@ -38,6 +38,11 @@ public class SysUserPostServiceImpl implements SysUserPostService {
|
||||
return sysUserPostMapper.selectPostIdsByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> selectUsedPostNameByIds(List<String> postIds) {
|
||||
return sysUserPostMapper.selectUsedPostNameByIds(postIds);
|
||||
}
|
||||
|
||||
private QueryWrapper<SysUserPost> createWrapper(String userId) {
|
||||
QueryWrapper<SysUserPost> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
|
@ -40,8 +40,8 @@ public class SysUserRoleServiceImpl implements SysUserRoleService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> selectRoleIdsByUserId(String userId) {
|
||||
return sysUserRoleMapper.selectRoleIdsByUserId(userId);
|
||||
public List<String> selectRoleIdsByUserId(String userId, String status) {
|
||||
return sysUserRoleMapper.selectRoleIdsByUserId(userId, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,7 +17,9 @@ import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.common.security.utils.SecurityUtil;
|
||||
import com.qiaoba.common.redis.constants.CacheConstant;
|
||||
import com.qiaoba.common.redis.service.RedisService;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.module.system.mapper.SysUserMapper;
|
||||
import com.qiaoba.module.system.service.SysUserPostService;
|
||||
import com.qiaoba.module.system.service.SysUserRoleService;
|
||||
@ -41,6 +43,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
private final SysUserMapper sysUserMapper;
|
||||
private final SysUserPostService sysUserPostService;
|
||||
private final SysUserRoleService sysUserRoleService;
|
||||
private final RedisService redisService;
|
||||
|
||||
@Override
|
||||
public int saveOrUpdate(SysUserDto dto, Boolean isUpdate) {
|
||||
@ -71,6 +74,14 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
return sysUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysUser selectByUsername(String username) {
|
||||
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
.eq(SysUser::getUsername, username);
|
||||
return sysUserMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int resetPwd(ResetPwdDto dto) {
|
||||
// todo 加密密码
|
||||
@ -157,7 +168,6 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
|
||||
private SysUser dtoToSysUser(SysUserDto dto, Boolean isUpdate) {
|
||||
if (StrUtil.isNotBlank(dto.getPassword())) {
|
||||
// todo 加密密码
|
||||
dto.setPassword("123456");
|
||||
}
|
||||
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
|
||||
|
@ -19,4 +19,12 @@
|
||||
order by d.parent_id, d.order_num
|
||||
</select>
|
||||
|
||||
<select id="existChild" resultType="string">
|
||||
SELECT dept_id FROM sys_dept where parent_id = #{deptId} LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="existUsed" resultType="string">
|
||||
SELECT nickname from sys_user where dept_id = #{deptId} and is_delete = '0' limit 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -24,11 +24,25 @@
|
||||
<select id="selectByUserId" resultType="com.qiaoba.api.system.entity.vo.SysMenuVo">
|
||||
select distinct t1.menu_id, t1.parent_id, t1.menu_name, t1.path, t1.component, t1.`query`, t1.is_visible, t1.perms, t1.is_frame, t1.is_cache, t1.menu_type, t1.icon, t1.order_num, t1.create_time
|
||||
from sys_menu t1
|
||||
left join sys_role_menu t2 on t1.menu_id = t2.menu_id
|
||||
left join sys_user_role t3 on t2.role_id = t3.role_id
|
||||
left join sys_role t4 on t3.role_id = t4.role_id
|
||||
left join sys_user t5 on t3.user_id = t5.user_id
|
||||
where t5.user_id = #{userId} and t1.menu_type in ('M', 'C') AND t4.status = '1'
|
||||
LEFT JOIN sys_role_menu t2
|
||||
on t2.menu_id = t1.menu_id
|
||||
LEFT JOIN sys_role t3
|
||||
on t3.role_id = t2.role_id
|
||||
LEFT JOIN sys_user_role t4
|
||||
on t4.role_id = t3.role_id
|
||||
where t4.user_id = #{userId} and t1.menu_type in ('M', 'C') AND t3.status = '1'
|
||||
order by t1.parent_id, t1.order_num
|
||||
</select>
|
||||
|
||||
<select id="selectPermsByUserId" resultType="string">
|
||||
SELECT t1.perms
|
||||
from sys_menu t1
|
||||
LEFT JOIN sys_role_menu t2
|
||||
on t2.menu_id = t1.menu_id
|
||||
LEFT JOIN sys_role t3
|
||||
on t3.role_id = t2.role_id
|
||||
LEFT JOIN sys_user_role t4
|
||||
on t4.role_id = t3.role_id
|
||||
where t4.user_id = #{userId} AND t3.status = '1'
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -4,8 +4,8 @@
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.qiaoba.module.system.mapper.SysPostMapper">
|
||||
|
||||
<select id="checkPostNameUnique" resultType="int">
|
||||
select count(post_id) from sys_post
|
||||
<select id="checkPostNameUnique" resultType="string">
|
||||
select post_id from sys_post
|
||||
where post_name = #{postName}
|
||||
<if test="postId != null and postId != ''">
|
||||
and post_id != #{postId}
|
||||
@ -13,8 +13,8 @@
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="checkPostCodeUnique" resultType="int">
|
||||
select count(post_id) from sys_post
|
||||
<select id="checkPostCodeUnique" resultType="string">
|
||||
select post_id from sys_post
|
||||
where post_code = #{postCode}
|
||||
<if test="postId != null and postId != ''">
|
||||
and post_id != #{postId}
|
||||
|
@ -7,4 +7,16 @@
|
||||
<select id="selectPostIdsByUserId" resultType="string">
|
||||
select post_id from sys_user_post where user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="selectUsedPostNameByIds" resultType="string">
|
||||
select DISTINCT t1.post_name
|
||||
from sys_post t1
|
||||
LEFT JOIN sys_user_post t2
|
||||
on t1.post_id = t2.post_id
|
||||
where t2.post_id in
|
||||
<foreach collection="list" item="postId" open="(" separator="," close=")">
|
||||
#{postId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -5,7 +5,12 @@
|
||||
<mapper namespace="com.qiaoba.module.system.mapper.SysUserRoleMapper">
|
||||
|
||||
<select id="selectRoleIdsByUserId" resultType="string">
|
||||
select role_id from sys_user_role where user_id = #{userId}
|
||||
select t1.role_id from sys_user_role t1
|
||||
left join sys_role t2 on t2.role_id = t1.role_id
|
||||
where t1.user_id = #{userId}
|
||||
<if test="status != null and status != ''">
|
||||
and t2.status = #{status}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<delete id="deleteByRoleIdAndUserIds">
|
||||
|
Reference in New Issue
Block a user