苏电e学堂权限附加功能

1、代码融合、分包分层次,并且可以正常给角色添加权限
2、表结构已将权限表与苏电e学堂t_user表融合
This commit is contained in:
xianing 2023-08-10 10:18:46 +08:00
parent c6f6a59363
commit 9eed5e47ae
255 changed files with 11622 additions and 261 deletions

166
pom.xml
View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version> <version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.lingu.suElec</groupId> <groupId>com.lingu.suElec</groupId>
@ -15,8 +15,15 @@
<description>Demo project for Spring Boot</description> <description>Demo project for Spring Boot</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<!--<swagger-ui.version>2.9.2</swagger-ui.version>--> <swagger.version>2.9.2</swagger.version>
<!--<springfox.version>2.9.2</springfox.version>--> <jjwt.version>0.9.1</jjwt.version>
<mybatis-spring.version>1.3.2</mybatis-spring.version>
<fastjson.version>1.2.62</fastjson.version>
<shiro-spring.version>1.4.1</shiro-spring.version>
<jbcrypt.version>0.4</jbcrypt.version>
<pagehelper-spring-boot-starter.version>1.2.12</pagehelper-spring-boot-starter.version>
<!--<thymeleaf-extras-shiro.version>2.0.0</thymeleaf-extras-shiro.version>-->
<druid-spring-boot-starter.version>1.1.10</druid-spring-boot-starter.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -34,14 +41,7 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!--Mybatis部分-->
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.18</version>
</dependency>
<!--mybatis启动器--> <!--mybatis启动器-->
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>org.mybatis.spring.boot</groupId>
@ -56,17 +56,110 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<!--swagger文档--> <!-- aop 依赖-->
<!--<dependency>--> <dependency>
<!--<groupId>io.springfox</groupId>--> <groupId>org.springframework.boot</groupId>
<!--<artifactId>springfox-swagger2</artifactId>--> <artifactId>spring-boot-starter-aop</artifactId>
<!--<version>${springfox.version}</version>--> </dependency>
<!--</dependency>--> <!-- thymeleaf 依赖-->
<!--<dependency>--> <dependency>
<!--<groupId>io.springfox</groupId>--> <groupId>org.springframework.boot</groupId>
<!--<artifactId>springfox-swagger-ui</artifactId>--> <artifactId>spring-boot-starter-thymeleaf</artifactId>
<!--<version>${springfox.version}</version>--> </dependency>
<!--</dependency>-->
<!--redis 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis创建连接池默认不会创建连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- commoons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<!-- ***************** 手动引入 **************** -->
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-spring-boot-starter.version}</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- jbcrypt -->
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>${jbcrypt.version}</version>
</dependency>
<!-- shiro - shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro-spring.version}</version>
</dependency>
<!-- Shiro 标签 thymeleaf-extras-shiro -->
<!--<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>${thymeleaf-extras-shiro.version}</version>
</dependency>-->
<!-- druid数据源这里我只使用日志监控 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid-spring-boot-starter.version}</version>
</dependency>
@ -77,6 +170,35 @@
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<executions>
<execution>
<phase>deploy</phase>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
</dependencies>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

View File

@ -1,14 +0,0 @@
package com.lingu.suelec.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//@EnableSwagger2
public class StudyApplication {
public static void main(String[] args) {
SpringApplication.run(StudyApplication.class, args);
}
}

View File

@ -1,52 +0,0 @@
//package com.lingu.suelec.study.config;
//
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import springfox.documentation.builders.ApiInfoBuilder;
//import springfox.documentation.builders.ParameterBuilder;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.schema.ModelRef;
//import springfox.documentation.service.ApiInfo;
//import springfox.documentation.service.Parameter;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spring.web.plugins.Docket;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//
//import java.util.ArrayList;
//import java.util.List;
//
//@Configuration
//@EnableSwagger2
//public class SwaggerConfig {
//
// @Bean
// public Docket createRestApi() {
// return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
// .apis(RequestHandlerSelectors.basePackage("com.lingu.suelec.study.controller")).paths(PathSelectors.any())
// .build().globalOperationParameters(setHeaderToken());
//
// }
//
// private ApiInfo apiInfo() {
// return new ApiInfoBuilder().title("action-swagger").description("swagger实战").termsOfServiceUrl("")
// .version("1.0").build();
// }
//
// /**
// * @Description: 设置swagger文档中全局参数
// * @param
// * @Date: 2020/9/11 10:15
// * @return: java.util.List<springfox.documentation.service.Parameter>
// */
//
// private List<Parameter> setHeaderToken() {
// List<Parameter> pars = new ArrayList<>();
// ParameterBuilder userId = new ParameterBuilder();
//// userId.name("token").description("用户TOKEN").modelRef(new ModelRef("string")).parameterType("header")
//// .required(true).build();
// pars.add(userId.build());
// return pars;
// }
//}
//

View File

@ -1,20 +0,0 @@
//package com.lingu.suelec.study.config;
//
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.servlet.config.annotation.EnableWebMvc;
//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//@Configuration
//@EnableWebMvc
//public class WebMvcConfig implements WebMvcConfigurer {
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// //兼容swagger老版本v1,v2
// registry.addResourceHandler("/statics/**").addResourceLocations("classpath:/statics/");
// registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
// registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
// registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
// registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
// registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
// }
//}

View File

@ -1,17 +0,0 @@
package com.lingu.suelec.study.mapper;
import com.lingu.suelec.study.domain.TrainInfo;
import com.lingu.suelec.study.domain.TrainingClass;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface TrainMapper {
TrainInfo selectTrainInfo(String userId);
List<TrainInfo> selectTtrainClassList();
}

View File

@ -1,13 +0,0 @@
package com.lingu.suelec.study.service;
import com.lingu.suelec.study.domain.TrainInfo;
import com.lingu.suelec.study.domain.TrainingClass;
import org.springframework.stereotype.Service;
import java.util.List;
public interface TrainService {
TrainInfo selectTrainInfo(String id);
List<TrainInfo> selectTtrainClassList(String id);
}

View File

@ -1,29 +0,0 @@
package com.lingu.suelec.study.service.impl;
import com.lingu.suelec.study.domain.TrainInfo;
import com.lingu.suelec.study.domain.TrainingClass;
import com.lingu.suelec.study.mapper.TrainMapper;
import com.lingu.suelec.study.service.TrainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class TrainServiceImpl implements TrainService{
@Resource
TrainMapper trainMapper;
@Override
public TrainInfo selectTrainInfo(String id) {
TrainInfo trainingClass = trainMapper.selectTrainInfo(id);
return trainingClass;
}
@Override
public List<TrainInfo> selectTtrainClassList(String id) {
List<TrainInfo> list = trainMapper.selectTtrainClassList();
return list;
}
}

View File

@ -0,0 +1,15 @@
package com.suelec;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(value = "com.suelec.**.dao")
@SpringBootApplication
public class SpringbootShiroApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootShiroApplication.class, args);
}
}

View File

@ -0,0 +1,24 @@
package com.suelec.permission.aop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解记录日志
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
/**
* 记录用户操作哪个模块
*/
String title() default "";
/**
* 记录用户操作的动作
*/
String action() default "";
}

View File

@ -0,0 +1,118 @@
package com.suelec.permission.aop.aspect;
import com.alibaba.fastjson.JSON;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.dao.SysLogDao;
import com.suelec.permission.pojo.SysLog;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.utils.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* aop切面
*/
@Aspect
@Component
public class SysLogAspect {
private static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
@Autowired
private IdWorker idWorker;
@Autowired
private SysLogDao sysLogDao;
/**
* 配置切入点配置为自定义注解
*/
@Pointcut("@annotation(com.suelec.permission.aop.annotation.MyLog)")
public void logPointCut(){};
/**
* 环绕通知
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 开始时间
long startTime = System.currentTimeMillis();
//执行方法
Object proceed = joinPoint.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - startTime;
// 保存日志
try {
saveLog(joinPoint,time);
} catch (Exception e) {
logger.error("【记录日志】,{}",e);
}
return proceed;
}
/**
* 日志入库
* @param joinPoint
* @param time
*/
private void saveLog(ProceedingJoinPoint joinPoint,long time) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
//Class classzz = signature.getDeclaringType();// 获取控制器包含报包名
String className = joinPoint.getTarget().getClass().getName();// 获取控制器包含报包名
String methodName = signature.getName();// 获取方法名
Object[] args = joinPoint.getArgs();// 获取参数
// 打印该方法耗时时间
logger.info("请求{}.{}耗时{}毫秒",className,methodName,time);
SysLog sysLog = new SysLog();
sysLog.setId(String.valueOf(idWorker.nextId()));
sysLog.setMethod(className + "." + methodName);
try {// 可能会出现转换错误
sysLog.setParams(args.length != 0 ?JSON.toJSONString(args) : "");
} catch (Exception e) {}
// 获取自定义注解的字段值
MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
if (myLog != null){
// 注解上的描述
sysLog.setOperation(myLog.title() + "-" + myLog.action());
}
// 获取 ip
String ip = request.getRemoteAddr();
sysLog.setIp(ip);
logger.info("【Ip】{},【接口地址】{},【请求方式】{},【入参】:{}",sysLog.getIp(),request.getRequestURL(),request.getMethod(),sysLog.getParams());
String token = request.getHeader(Constant.ACCESS_TOKEN);
Claims claims = JwtTokenUtil.getInstance().parseToken(token);
String userId=null;
String username=null;
if (claims != null){
userId = claims.getSubject();
username = (String) claims.get(Constant.JWT_USER_NAME);
}
sysLog.setUserId(userId);
sysLog.setUsername(username);
sysLog.setTime((int) time);
sysLog.setCreateTime(new Date());
logger.info("【日志数据】,{}",sysLog.toString());
sysLogDao.insertSelective(sysLog);
}
}

View File

@ -0,0 +1,17 @@
package com.suelec.permission.config;
import com.suelec.permission.utils.IdWorker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 添加 bean 到容器中
*/
@Configuration
public class BeanConfig {
@Bean
public IdWorker idWorker(){
return new IdWorker(1,1);
}
}

View File

@ -0,0 +1,44 @@
package com.suelec.permission.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域配置
*/
@Configuration
public class CorsConfig {
/**
* 跨域配置
* @return
*/
private CorsConfiguration apiCorsConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("Origin");
corsConfiguration.addAllowedHeader("X-Requested-With");
corsConfiguration.addAllowedHeader("Content-Type");
corsConfiguration.addAllowedHeader("Accept");
corsConfiguration.addAllowedHeader("authorization");
corsConfiguration.addAllowedMethod(HttpMethod.GET);
corsConfiguration.addAllowedMethod(HttpMethod.POST);
corsConfiguration.addAllowedMethod(HttpMethod.PUT);
corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
corsConfiguration.addAllowedMethod(HttpMethod.OPTIONS);
corsConfiguration.setMaxAge(3600L); // 预检请求的有效期单位为秒
corsConfiguration.setAllowCredentials(true);// 是否允许用户发送处理 cookie
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", apiCorsConfig());
return new CorsFilter(source);
}
}

View File

@ -0,0 +1,28 @@
package com.suelec.permission.config;
import com.suelec.permission.serializer.MyStringRedisSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @ClassName: RedisConfig
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> redisTemplate=new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
MyStringRedisSerializer myStringRedisSerializer=new MyStringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(myStringRedisSerializer);
redisTemplate.setValueSerializer(myStringRedisSerializer);
return redisTemplate;
}
}

View File

@ -0,0 +1,81 @@
package com.suelec.permission.config;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Value("${swagger2.enable}")
private boolean enable;
@Bean
public Docket createRestApi() {
/**
* 这是为了我们在用 swagger 测试接口的时候添加头部信息
*/
List<Parameter> pars = new ArrayList<Parameter>();
ParameterBuilder tokenPar = new ParameterBuilder();
ParameterBuilder refreshTokenPar = new ParameterBuilder();
tokenPar.name("authorization").description("swagger测试用(模拟authorization传入)非必填 header").modelRef(new ModelRef("string")).parameterType("header").required(false);
refreshTokenPar.name("refresh_token").description("swagger测试用(模拟刷新token传入)非必填 header").modelRef(new ModelRef("string")).parameterType("header").required(false);
/**
* 多个的时候 就直接添加到 pars 就可以了
*/
pars.add(tokenPar.build());
pars.add(refreshTokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(getBasePackages())
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars)
.enable(enable);
}
// 设置多路径
private Predicate<RequestHandler> getBasePackages() {
Predicate<RequestHandler> predicate = Predicates.and(RequestHandlerSelectors.basePackage("com.suelec.permission.controller")); // 扫描com.fan.ams.controller包
predicate = Predicates.and(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class), predicate); // 扫描com.fan.ams.controller包下有@ApiOperation和上面是交集
predicate = Predicates.or(RequestHandlerSelectors.basePackage("com.suelec.trainclass.controller"), predicate);// 扫描com.fan.ams.controller222包和上面是并集
return predicate;
}
/**
* @Description: 构建 api文档的信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 设置页面标题
.title("shiro权限管理系统后端api接口文档")
// 设置联系人
.contact(new Contact("shiro-小池", "http://www.imooc.com", "875267425@163.com"))
// 描述
.description("shrio权限管理系统接口文档这里是描述信息")
// 定义版本号
.version("1.0").build();
}
}

View File

@ -0,0 +1,38 @@
package com.suelec.permission.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
@Configuration
@ConfigurationProperties(prefix = "jwt")
@Data
public class TokenConfig {
/**
* 发行者
*/
private String issuer;
/**
* 密钥
*/
private String secretKey;
/**
* token 过期时间
*/
private Duration accessTokenExpireTime;
/**
* pc端 刷新 token 过期时间
*/
private Duration refreshTokenExpireTime;
/**
* app端 刷新 token 过期时间
*/
private Duration refreshTokenExpireAppTime;
}

View File

@ -0,0 +1,50 @@
package com.suelec.permission.constarts;
/**
* @ClassName: Constant
*/
public interface Constant {
/**
* 用户名称 key用于生成token与只能一个账号同时存在
*/
String JWT_USER_NAME="jwt-user-name-key";
/**
* 权限key
*/
String JWT_PERMISSIONS_KEY="jwt-permissions-key_";
/**
* 角色key
*/
String JWT_ROLES_KEY="jwt-roles-key_";
/**
* 标记用户需要重新登录场景 比如修改了用户的角色/权限/菜单
*/
String JWT_USER_LOGIN_BLACKLIST="jwt-access-token-blacklist_";
/**
* 正常token
*/
String ACCESS_TOKEN="authorization";
/**
* 标记用户是否已经被锁定
*/
String ACCOUNT_LOCK_KEY="account-lock-key_";
/**
* 标记用户是否已经删除
*/
String DELETED_USER_KEY="deleted-user-key_";
/**
* 用户权鉴缓存 key
*/
String IDENTIFY_CACHE_KEY="shiro-cache:com.xh.lesson.shiro.CustomRealm.authorizationCache:";
}

View File

@ -0,0 +1,33 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.service.HomeService;
import com.suelec.permission.utils.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/api")
@Api(value = "首页模块",tags = "首页相关模块")
public class HomeController {
@Autowired
private HomeService homeService;
@MyLog(title = "首页模块",action = "获取首页数据接口")
@ApiOperation(value = "获取首页数据接口",notes = "首页数据")
@GetMapping("/home")
public Response getHome(HttpServletRequest request){
/* String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
String userId = JwtTokenUtil.getInstance().getUserId(accessToken);
return homeService.getHome(userId);*/
return null;
}
}

View File

@ -0,0 +1,81 @@
package com.suelec.permission.controller;
import io.swagger.annotations.Api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 这个文件是我之前不分离时用到的现在使用分离开发用不到注释掉了
*/
@Controller
@RequestMapping("/index")
@Api(value = "视图",tags = "跳转试图的控制器")
public class IndexController {
/*@ApiOperation(value = "登陆页面",notes = "跳转登陆页面")
@GetMapping("/login")
public String login(){
return "login";
}
@ApiOperation(value = "首页",notes = "跳转首页页面")
@GetMapping("/home")
public String home(){
return "home";
}
@ApiOperation(value = "首页",notes = "跳转主体页面")
@GetMapping("/main")
public String main(){
return "main";
}
@ApiOperation(value = "菜单权限管理页面", notes = "权限管理页面")
@GetMapping("/menus")
public String menus(){
return "menus/menu";
}
@ApiOperation(value = "跳转角色管理页面", notes = "角色管理页面")
@GetMapping("/roles")
public String roles(){
return "roles/role";
}
@ApiOperation(value = "跳转部门管理页面",notes = "部门管理页面")
@GetMapping("/depts")
public String depts(){
return "depts/dept";
}
@ApiOperation(value = "跳转用户管理页面",notes = "用户管理页面")
@GetMapping("/users")
public String users(){
return "users/user";
}
@GetMapping("/logs")
@ApiOperation(value = "跳转日志管理页面",notes = "日志管理页面")
public String logs(){
return "logs/log";
}
@ApiOperation(value = "跳转个人信息编辑页面",notes = "个人信息编辑页面")
@GetMapping("/users/info")
public String usersInfo(){
return "users/user_edit";
}
@GetMapping("/users/pwd")
@ApiOperation(value = "跳转用户编辑密码页面",notes = "用户编辑密码页面")
public String updatePwd(){
return "users/user_pwd";
}
@ApiOperation(value = "404",notes = "跳转404错误页面")
@GetMapping("/404")
public String error404(){
return "error/404";
}*/
}

View File

@ -0,0 +1,44 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.pojo.SysLog;
import com.suelec.permission.service.LogService;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LogPageReqVo;
import com.suelec.permission.vo.resp.PageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(value = "系统管理-日志管理",tags = "日志管理相关接口")
@RestController
@RequestMapping("/api")
public class LogController {
@Autowired
private LogService logService;
@ApiOperation(value = "分页查找操作日志",notes = "分页查找操作日志接口")
@RequiresPermissions("sys:log:list")
@PostMapping("/logs")
public Response<PageVo<SysLog>> pageInfo(@RequestBody LogPageReqVo logPageReqVo){
return logService.pageInfo(logPageReqVo);
}
@ApiOperation(value = "删除日志",notes = "删除日志接口")
@RequiresPermissions("sys:log:delete")
@MyLog(title = "系统管理-日志管理",action = "删除日志接口")
@DeleteMapping("/log")
public Response<String> deletedLog(@RequestBody @ApiParam(value = "日志id集合") List<String> logIds){
return logService.deletedLog(logIds);
}
}

View File

@ -0,0 +1,82 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.service.PermissionService;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.PermissionAddReqVo;
import com.suelec.permission.vo.req.PermissionUpdateReqVo;
import com.suelec.permission.vo.resp.PermissionRespNodeTreeVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
@Api(value = "组织管理-菜单权限管理",tags = "菜单权限管理相关接口")
@RestController
@RequestMapping("/api")
public class PermissionController {
@Autowired
private PermissionService permissionService;
@ApiOperation(value = "获取所有权限(包括按钮)",notes = "角色添加/编辑/分配权限时用到的结果数据")
@RequiresPermissions(value = {"sys:role:update","sys:role:add"},logical = Logical.OR)
@MyLog(title = "组织管理-菜单权限管理",action = "获取所有的菜单权限数据接口")
@GetMapping("/permissions/tree/all")
public Response getAllPermissionTree(){
return Response.success(permissionService.selectAllTree());
}
@ApiOperation(value = "菜单权限表格展示-获取所有的菜单权限数据接口",notes = "菜单权限接口")
@RequiresPermissions("sys:permission:list")
@MyLog(title = "组织管理-菜单权限管理",action = "只递归查询到菜单结构数据接口")
@GetMapping("/permissions")
public Response getAllPermission(){
return Response.success(permissionService.selectAll());
}
@ApiOperation(value = "菜单权限树",notes = "只递归查询目录与菜单,不要按钮,添加/编辑-权限的上级选择权限树结构展示")
@MyLog(title = "组织管理-菜单权限管理",action = "新增菜单权限接口")
@RequiresPermissions(value = {"sys:permission:update","sys:permission:add"},logical = Logical.OR)
@GetMapping("/permissions/tree")
public Response<List<PermissionRespNodeTreeVo>> getAllPermissionTreeExBtn(){
return permissionService.selectAllMenuByTree();
}
@ApiOperation(value = "新增权限",notes = "新增菜单权限接口")
@RequiresPermissions("sys:permission:add")
@MyLog(title = "组织管理-菜单权限管理",action = "新增菜单权限接口")
@PostMapping("/permission")
public Response<String> createPermission(@RequestBody @Valid PermissionAddReqVo permissionAddReqVO){
return permissionService.addPermission(permissionAddReqVO);
}
@ApiOperation(value = "更新权限",notes = "新更新菜单权限接口")
@RequiresPermissions("sys:permission:update")
@MyLog(title = "组织管理-菜单权限管理",action = "编辑菜单权限接口")
@PutMapping("/permission")
public Response<String> updatePermission(@RequestBody @Valid PermissionUpdateReqVo permissionUpdateReqVo){
return permissionService.updatePermission(permissionUpdateReqVo);
}
@ApiOperation(value = "删除权限",notes = "删除菜单权限接口")
@RequiresPermissions("sys:permission:delete")
@MyLog(title = "组织管理-菜单权限管理",action = "删除菜单权限接口")
@DeleteMapping("/permission/{permissionId}")
public Response<String> deletedPermission(@PathVariable("permissionId") String permissionId){
return permissionService.deletedPermission(permissionId);
}
}

View File

@ -0,0 +1,87 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.service.RoleService;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.RolePageReqVo;
import com.suelec.permission.vo.req.RoleReqVo;
import com.suelec.permission.vo.req.RoleUpdateReqVo;
import com.suelec.permission.vo.resp.PageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Set;
@Api(value = "组织管理-角色管理",tags = "角色管理相关接口")
@RestController
@RequestMapping("/api")
public class RoleController {
@Autowired
private RoleService roleService;
@ApiOperation(value = "分页获取角色数据接口",notes = "分页获取角色数据接口")
@RequiresPermissions("sys:role:list")
@MyLog(title = "组织管理-角色管理",action = "分页获取角色数据接口")
@PostMapping("/roles")
public Response<PageVo> pageInfo(@RequestBody RolePageReqVo rolePageReqVo){
return roleService.pageInfoRoles(rolePageReqVo);
}
@ApiOperation(value = "新增角色接口",notes = "新增角色")
@RequiresPermissions("sys:role:add")
@MyLog(title = "组织管理-角色管理",action = "新增角色接口")
@PostMapping("/role")
public Response<String> createRole(@RequestBody @Valid RoleReqVo roleReqVo){
return roleService.createRole(roleReqVo);
}
@ApiOperation(value = "获取角色详情接口",notes = "获取角色详情接口")
@RequiresPermissions("sys:role:detail")
@MyLog(title = "组织管理-角色管理",action = "获取角色详情接口")
@GetMapping("/role/{id}")
public Response<Set<String>> detailInfo(@PathVariable("id") String roleId){
return roleService.detailInfo(roleId);
}
@ApiOperation(value = "更新角色信息",notes = "更新角色信息接口")
@RequiresPermissions("sys:role:update")
@MyLog(title = "组织管理-角色管理",action = "更新角色信息接口")
@PutMapping("/role")
public Response<String> updateRole(@RequestBody @Valid RoleUpdateReqVo roleUpdateReqVo){
return roleService.updateRole(roleUpdateReqVo);
}
@ApiOperation(value = "更新角色状态",notes = "更新角色状态接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "id",value = "用户id",required = true,dataType = "String",paramType = "form"),
@ApiImplicitParam(name = "status",value = "状态status",required = true,dataType = "Integer",paramType = "form"),
})
@RequiresPermissions("sys:role:update:status")
@MyLog(title = "组织管理-角色管理",action = "更新角色状态接口")
@PostMapping("/role/{id}/{status}")
public Response<String> updateRoleStatus(@PathVariable("id")String roleId,@PathVariable("status") Integer status){
return roleService.updateRoleStatus(roleId,status);
}
@ApiOperation(value = "删除角色信息",notes = "删除角色接口")
@RequiresPermissions("sys:role:delete")
@MyLog(title = "组织管理-角色管理",action = "删除角色接口")
@DeleteMapping("/role/{id}")
public Response<String> deletedRole(@PathVariable("id") String roleId){
return roleService.deletedRole(roleId);
}
}

View File

@ -0,0 +1,49 @@
package com.suelec.permission.controller;
public class Test {
public static void main(String[] args) {
String str = "aaabbabbb";
System.out.println(strCount(str));// a3b2ab3
}
private static String strCount(String str){
String[] strs = str.split("");
String newStr = strs[0],index = strs[0];
int count = 0;
for (int i = 0,len = strs.length; i < len; i++){
if (strs[i].equals(index)){
count++;
}else{
newStr += count == 1 ? strs[i] : count + strs[i];
count = 1;
}
index = strs[i];
}
return newStr + count;
}
private static String yasuo(String str) {
String[] strs = str.split("");
String newStr = strs[0];
String index = "";
int count = 0;
index = strs[0];
for (int i = 0; i < strs.length; i ++) {
if (!strs[i].equals(index)) {
if (count != 1) {
newStr += count + strs[i];
} else {
newStr += strs[i];
}
count = 1;
} else {
count ++;
}
index = strs[i];
}
return newStr;
}
}

View File

@ -0,0 +1,38 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.utils.FileUtil;
import com.suelec.permission.utils.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
@Api(tags = "上传文件")
@RestController
@RequestMapping("/api")
public class UploadController {
@ApiOperation(value = "头像上传",notes = "头像上传接口")
@MyLog(title = "上传头像",action = "上传头像的接口")
@PostMapping(value = "/upload",headers = "content-type=multipart/form-data")
public Response upload(@ApiParam(value = "头像上传",required = true) MultipartFile file) throws IOException {
String[] type = {"jpg","jpeg","png","gif"};
if (!Arrays.asList(type).contains(FileUtil.getFileType(file.getBytes()))){
return Response.error("文件格式错误");
}
if (!FileUtil.checkFileSize(file.getSize(),30,"k")){
return Response.error("文件不能超过30K");
}
String path = "D:\\upload";
String fileName = FileUtil.upload(file, path);
return Response.success("文件路径:" + fileName);
}
}

View File

@ -0,0 +1,177 @@
package com.suelec.permission.controller;
import com.suelec.permission.aop.annotation.MyLog;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.service.UserService;
import com.suelec.permission.utils.JwtTokenUtil;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LoginReqVo;
import com.suelec.permission.vo.req.UserAddReqVo;
import com.suelec.permission.vo.req.UserOwnRoleReqVo;
import com.suelec.permission.vo.req.UserPageReqVo;
import com.suelec.permission.vo.req.UserUpdateDetailInfoReqVo;
import com.suelec.permission.vo.req.UserUpdatePasswordReqVo;
import com.suelec.permission.vo.req.UserUpdateReqVo;
import com.suelec.permission.vo.resp.LoginRespVo;
import com.suelec.permission.vo.resp.PageVo;
import com.suelec.permission.vo.resp.UserOwnRoleRespVo;
import com.suelec.permission.vo.resp.UserRespVo;
import com.suelec.permission.vo.resp.UserTableRespVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
@Api(value = "用户登陆/登出",tags = "用户登陆/登出相关的接口")
@RestController
@RequestMapping("/api")
public class UserController {
private static Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
/**
* 登陆
* @param loginReqVo
* @return
*/
@ApiOperation(value = "用户登陆",notes = "用户登陆的接口")
@PostMapping("/login")
public Response<LoginRespVo> login(@RequestBody @Valid LoginReqVo loginReqVo){
return userService.login(loginReqVo);
}
/**
* 登出
* @param request
* @return
*/
@ApiOperation(value = "用户登出",notes = "用户登出的接口")
@GetMapping("/logout")
public Response<String> logout(HttpServletRequest request){
String accessToken = null;
//String refreshToken = null;
// 退出时不管成功还是失败都要退出
try {
accessToken = request.getHeader(Constant.ACCESS_TOKEN);
//refreshToken = request.getHeader(Constant.REFRESH_TOKEN);
return userService.logout(accessToken);
} catch (Exception e) {
logger.error("【logout error】{}",e);
}
return Response.success();
}
@MyLog(title = "组织管理-用户管理",action = "分页查询用户接口")
@RequiresPermissions("sys:user:list")
@ApiOperation(value = "分页查询用户",notes = "分页查询用户接口")
@PostMapping("/users")
public Response<PageVo<UserTableRespVo>> pageInfo(@RequestBody @Valid UserPageReqVo userPageReqVo){
return userService.pageInfo(userPageReqVo);
}
@ApiOperation(value = "新增用户",notes = "新增用户接口")
@RequiresPermissions("sys:user:add")
@MyLog(title = "组织管理-用户管理",action = "新增用户接口")
@PostMapping("/user")
public Response<String> addUser(@RequestBody @Valid UserAddReqVo userAddReqVo){
return userService.addUser(userAddReqVo);
}
@MyLog(title = "组织管理-用户管理",action = "查询用户拥有的角色数据接口")
@ApiOperation(value = "查询用户拥有的角色数据接口",notes = "查询用户拥有的角色数据接口")
@GetMapping("/user/roles/{userId}")
public Response<UserOwnRoleRespVo> getUserOwnRole(@PathVariable("userId")String userId){
return userService.getUserOwnRole(userId);
}
@ApiOperation(value = "更新用户角色",notes = "保存用户拥有的角色信息接口")
@RequiresPermissions("sys:user:role:update")
@MyLog(title = "组织管理-用户管理",action = "保存用户拥有的角色信息接口")
@PutMapping("/user/roles")
public Response<String> saveUserOwnRole(@RequestBody @Valid UserOwnRoleReqVo vo){
return userService.setUserOwnRole(vo);
}
@ApiOperation(value = "重新用户密码",notes = "重新用户密码接口")
@ApiImplicitParam(name = "userId",value = "用户id",required = true,dataType = "String",paramType = "form")
@RequiresPermissions("sys:user:role:update")
@MyLog(title = "组织管理-重置用户密码",action = "重置用户密码接口")
@GetMapping("/user/password/{id}")
public Response<String> resetUpdatePassword(@PathVariable("id") String userId){
return userService.resetUpdatePassword(userId);
}
/*@MyLog(title = "组织管理-用户管理",action = "jwt token 刷新接口")
@ApiOperation(value = "jwt token 刷新接口",notes = "jwt token 刷新接口")
@GetMapping("/user/token")
public Response<String> refreshToken(HttpServletRequest request){
String refreshToken=request.getHeader(Constant.REFRESH_TOKEN);
return userService.refreshToken(refreshToken);
}*/
@ApiOperation(value = "更新用户",notes = "更新用户接口")
@RequiresPermissions("sys:user:update")
@MyLog(title = "组织管理-用户管理",action = "列表修改用户信息接口")
@PutMapping("/user")
public Response<String> updateUserInfo(@RequestBody @Valid UserUpdateReqVo userUpdateReqVo,HttpServletRequest request){
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
String operationId = JwtTokenUtil.getInstance().getUserId(accessToken);// 操作人
return userService.updateUserInfo(userUpdateReqVo,operationId);
}
@ApiOperation(value = "批量/删除用户",notes = "批量/删除用户接口")
@RequiresPermissions("sys:user:delete")
@MyLog(title = "组织管理-用户管理",action = "批量/删除用户接口")
@DeleteMapping("/user")
public Response<String> deletedUsers(@RequestBody @ApiParam(value = "用户id集合")List<String> list,HttpServletRequest request){
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
String operationId = JwtTokenUtil.getInstance().getUserId(accessToken);// 操作人
return userService.deletedUsers(list,operationId);
}
@ApiOperation(value = "用户信息详情",notes = "用户信息详情接口")
@MyLog(title = "组织管理-用户管理",action = "用户信息详情接口")
@GetMapping("/user/info")
public Response<UserRespVo> detailInfo(HttpServletRequest request){
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
String userId = JwtTokenUtil.getInstance().getUserId(accessToken);
return userService.detailInfo(userId);
}
@ApiOperation(value = "保存个人信息",notes = "保存个人信息接口")
@MyLog(title = "组织管理-用户管理",action = "保存个人信息接口")
@PutMapping("/user/info")
public Response<String> saveUserInfo(@RequestBody UserUpdateDetailInfoReqVo updateDetailInfoReqVo, HttpServletRequest request){
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
String userId = JwtTokenUtil.getInstance().getUserId(accessToken);
return userService.userUpdateDetailInfo(updateDetailInfoReqVo,userId);
}
@ApiOperation(value = "修改个人密码",notes = "修改个人密码接口")
@MyLog(title = "组织管理-用户管理",action = "修改个人密码接口")
@PutMapping("/user/password")
public Response<String> updatePassword(@RequestBody @Valid UserUpdatePasswordReqVo userUpdatePasswordReqVo, HttpServletRequest request){
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
//String refreshToken = request.getHeader(Constant.REFRESH_TOKEN);
return userService.userUpdatePassword(userUpdatePasswordReqVo,accessToken);
}
}

View File

@ -0,0 +1,26 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysLog;
import com.suelec.permission.vo.req.LogPageReqVo;
import java.util.List;
public interface SysLogDao {
int insert(SysLog record);
int insertSelective(SysLog record);
/**
* 分页与条件查询所有数据
* @param logPageReqVo
* @return
*/
List<SysLog> selectAll(LogPageReqVo logPageReqVo);
/**
* 删除日志包括批量删除
* @param logIds
* @return
*/
int batchDeletedLog(List<String> logIds);
}

View File

@ -0,0 +1,40 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysPermission;
import java.util.List;
public interface SysPermissionDao {
int insert(SysPermission record);
int insertSelective(SysPermission record);
SysPermission selectByPrimaryKey(String permissionId);
/**
* 查询所有权限表格展示
* @return
*/
List<SysPermission> selectAll();
/**
* 通过用户id查询用户拥有的权限
* @param userId
* @return
*/
List<SysPermission> getPermissionByUserId(String userId);
/**
* 通过 id 查询是否有子级
* @param id
* @return
*/
int selectChild(String id);
/**
* 更新权限菜单数据
* @param permission
* @return
*/
int updateByPrimaryKeySelective(SysPermission permission);
}

View File

@ -0,0 +1,33 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysRole;
import com.suelec.permission.vo.req.RolePageReqVo;
import java.util.List;
public interface SysRoleDao {
int insert(SysRole record);
int insertSelective(SysRole record);
/**
* 角色管理分页数据查询
* @param rolePageReqVo
* @return
*/
List<SysRole> selectAll(RolePageReqVo rolePageReqVo);
/**
* 根据主键 id 查询
* @param roleId
* @return
*/
SysRole selectByPrimaryKey(String roleId);
/**
* 更新角色信息
* @param sysRole
* @return
*/
int updateByPrimaryKeySelective(SysRole sysRole);
}

View File

@ -0,0 +1,42 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysRolePermission;
import java.util.List;
public interface SysRolePermissionDao {
int insert(SysRolePermission record);
int insertSelective(SysRolePermission record);
/**
* 根据角色 id 删除多条角色 id 和菜单权限 id 关联数据
*/
int removeByRoleId(String roleId);
/**
* 批量插入角色和菜单权限关联
*/
int batchRolePermission(List<SysRolePermission> list);
/**
* 通过权限 id 查询所有的角色 id
* @param permissionId
* @return
*/
List<String> getRoleIdsByPermissionId(String permissionId);
/**
* 通过权限id删除相关角色和该菜单权限的关联表信息
* @param permissionId
* @return
*/
int removeByPermissionId(String permissionId);
/**
* 通过角色id查询拥有的权限id
* @param roleId
* @return
*/
List<String> getPermissionIdsByRoleId(String roleId);
}

View File

@ -0,0 +1,58 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysUser;
import com.suelec.permission.pojo.Tuser;
import com.suelec.permission.vo.req.UserPageReqVo;
import com.suelec.permission.vo.resp.UserTableRespVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface SysUserDao {
int insert(SysUser record);
int insertSelective(SysUser record);
/**
* 根据 username 用户名查询
* @param username
* @return
*/
Tuser findByUsername(@Param("username") String username);
/**
* 根据 id 主键查询
* @param userId
* @return
*/
SysUser selectByPrimaryKey(String userId);
/**
* 分页查询用户包括搜索条件
* @param userPageReqVo
* @return
*/
List<UserTableRespVo> selectAll(UserPageReqVo userPageReqVo);
/**
* 更新用户信息
* @param sysUser
* @return
*/
int updateSelective(SysUser sysUser);
/**
* 批量/删除用户接口
* @param sysUser
* @param list
* @return
*/
int deletedUsers(@Param("sysUser") SysUser sysUser, @Param("list") List<String> list);
/**
* 通过部门id集合统计用户
* @param deptIds
* @return
*/
int selectUserInfoByDeptIds(List<String> deptIds);
}

View File

@ -0,0 +1,73 @@
package com.suelec.permission.dao;
import com.suelec.permission.pojo.SysUserRole;
import java.util.List;
public interface SysUserRoleDao {
int insert(SysUserRole record);
int insertSelective(SysUserRole record);
/**
* 根据用户id 查询用户拥有的角色数据
*/
List<String> getRoleIdsByUserId(String userId);
/**
* 根据用户id 删除用户拥有的角色数据
* @param userId
*/
int removeRoleIdsByUserId(String userId);
/**
* 批量插入用户角色数据
* @param list
* @return
*/
int batchInsertUserRole(List<SysUserRole> list);
/**
* 通过角色 id 集合查询所有的用户 id
* @param roleIdsByPermissionId
* @return
*/
List<String> getUserIdsByRoleIds(List<String> roleIdsByPermissionId);
/**
* 通过 单个角色id 查询所有的用户ids
* @param roleId
* @return
*/
List<String> getUserIdsByRoleId(String roleId);
/**
* 通过角色id删除用户id
* @param roleId
* @return
*/
int removeUseIdsrRoleId(String roleId);
//================== 权限数据 ====================
/**
* 通过用户id获取该用户所拥有的角色名称用户登录时查询拥有角色
* @param userId
* @return
*/
List<String> getRoleNameByUserId(String userId);
/**
* 通过用户id获取该用户所拥有的权限授权 sys:user:add
* @param userId
* @return
*/
List<String> getPermissionPermsByUserId(String userId);
/**
* 查询前端按钮权限
* @param id
* @return
*/
List<String> getPermissionCodesByUserId(String id);
}

View File

@ -0,0 +1,8 @@
package com.suelec.permission.enums;
public interface BaseCodeEnum {
int getCode();
String getMessage();
}

View File

@ -0,0 +1,63 @@
package com.suelec.permission.enums;
/**
* 响应码
*/
public enum ResponseCode implements BaseCodeEnum {
/**
* 这个要和前段约定好
*code=1服务器已成功处理了请求 通常这表示服务器提供了请求的网页
*code=2授权异常 请求要求身份验证 客户端需要跳转到登录页面重新登录
*code=3 无权限访问资源
*code=-1(凭证过期) 客户端请求刷新凭证接口
*code=0表示请求失败只提示不跳转2 是跳转
*
*/
SUCCESS(1,"操作成功"),
SYSTEM_ERROR(0,"系统异常请稍后再试"),
DATA_ERROR(0,"参数异常"),
METHOD_IDENTITY_ERROR(0,"数据校验异常"),
ACCOUNT_ERROR(0,"该账号不存在"),
ACCOUNT_EXISTS_ERROR(0,"该账号已存在"),
ACCOUNT_LOCK(0,"该账号被锁定,请联系系统管理员"),
ACCOUNT_PASSWORD_ERROR(0,"用户名密码不匹配"),
TOKEN_ERROR(2,"用户未登录,请重新登录"),
TOKEN_NOT_NULL(-1,"token 不能为空"),
SHIRO_AUTHENTICATION_ERROR(0,"用户认证异常"),
ACCOUNT_HAS_DELETED_ERROR(2,"该账号已被删除,请联系系统管理员"),
TOKEN_PAST_DUE(-1,"登录失效,请重新登录"),
TOKEN_EXISTS(-1,"账号异地登录,你已被迫退出"),
NOT_PERMISSION(3,"没有权限访问该资源"),
OPERATION_ERROR(0,"操作失败"),
OPERATION_MENU_PERMISSION_CATALOG_ERROR(0,"操作后的菜单类型是目录,所属菜单必须为默认顶级菜单或者目录"),
OPERATION_MENU_PERMISSION_MENU_ERROR(0,"操作后的菜单类型是菜单,所属菜单必须为目录类型"),
OPERATION_MENU_PERMISSION_BTN_ERROR(0,"操作后的菜单类型是按钮,所属菜单必须为菜单类型"),
OPERATION_MENU_PERMISSION_URL_NOT_NULL(0,"菜单权限的url不能为空"),
OPERATION_MENU_PERMISSION_URL_PERMS_NULL(0,"菜单权限的标识符不能为空"),
OPERATION_MENU_PERMISSION_URL_METHOD_NULL(0,"菜单权限的请求方式不能为空"),
ACCOUNT_LOCK_TIP(2,"该账号被锁定,请联系系统管理员"),
OPERATION_MENU_PERMISSION_UPDATE(0,"操作的菜单权限存在子集关联不允许变更"),
ROLE_PERMISSION_RELATION(0, "该菜单权限存在子集关联,不允许删除"),
NOT_PERMISSION_DELETED_DEPT(0,"该组织机构下还关联着用户,不允许删除"),
OLD_PASSWORD_ERROR(0,"旧密码不匹配"),
OPERATION_MENU_PERMISSION_URL_CODE_NULL(0,"菜单权限的按钮标识不能为空"),
;
private int code;
private String message;
ResponseCode(int code,String message){
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,33 @@
package com.suelec.permission.exception;
import com.suelec.permission.enums.BaseCodeEnum;
public class BusinessException extends RuntimeException {
private int code;
private String message;
public BusinessException(String message){
super(message);
this.message = message;
}
public BusinessException(int code,String message){
super(message);
this.code = code;
this.message = message;
}
public BusinessException(BaseCodeEnum baseCodeEnum){
this(baseCodeEnum.getCode(),baseCodeEnum.getMessage());
}
public int getCode(){
return code;
}
public String getMessage(){
return message;
}
}

View File

@ -0,0 +1,73 @@
package com.suelec.permission.exception;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.utils.Response;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
/**
* 全局异常
*/
@RestControllerAdvice
public class HandlerException {
private static Logger logger = LoggerFactory.getLogger(HandlerException.class);
/**
* 捕获 MethodArgumentNotValidException
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response<String> handleBusinessException(MethodArgumentNotValidException e){
logger.error("【参数异常】,{}",e);
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
return Response.error(fieldError.getDefaultMessage());
}
/**
* 捕获 BusinessExceptionshiro授权
* @param e
* @return
*/
@ExceptionHandler(UnauthorizedException.class)
public Response<String> handleBusinessException(UnauthorizedException e){
logger.error("【权限异常】,{}",e);
return Response.error(ResponseCode.NOT_PERMISSION.getCode(),ResponseCode.NOT_PERMISSION.getMessage());
}
/**
* 捕获 BusinessException
* @param e
* @return
*/
@ExceptionHandler(BusinessException.class)
public Response<String> handleBusinessException(BusinessException e){
logger.error("【业务异常】,{}",e);
return Response.error(e.getCode(),e.getMessage());
}
/**
* 捕获 Exception
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public Response<String> handleException(Exception e){
if (e instanceof MaxUploadSizeExceededException){
logger.error("【上传文件异常】,{}",e);
return Response.error("文件最大不能超过1M");
}
logger.error("【系统异常】,{}",e);
return Response.error("系统异常");
}
}

View File

@ -0,0 +1,118 @@
package com.suelec.permission.pojo;
import java.io.Serializable;
import java.util.Date;
public class SysLog implements Serializable {
private String id;
private String userId;
private String username;
private String operation;
private Integer time;
private String method;
private String params;
private String ip;
private Date createTime;
private static final long serialVersionUID = 1L;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId == null ? null : userId.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation == null ? null : operation.trim();
}
public Integer getTime() {
return time;
}
public void setTime(Integer time) {
this.time = time;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method == null ? null : method.trim();
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params == null ? null : params.trim();
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip == null ? null : ip.trim();
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", userId=").append(userId);
sb.append(", username=").append(username);
sb.append(", operation=").append(operation);
sb.append(", time=").append(time);
sb.append(", method=").append(method);
sb.append(", params=").append(params);
sb.append(", ip=").append(ip);
sb.append(", createTime=").append(createTime);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,48 @@
package com.suelec.permission.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SysPermission implements Serializable {
private String id;
private String code;
private String title;
private String icon;
private String perms;
private String url;
private String method;
private String name;
private String pid;
private Integer orderNum;
private Integer type;
private Integer status;
private Date createTime;
private Date updateTime;
private Integer deleted;
private String pidName;
}

View File

@ -0,0 +1,29 @@
package com.suelec.permission.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class SysRole implements Serializable {
private String id;
private String name;
private String description;
private Integer status;
private Date createTime;
private Date updateTime;
private Integer deleted;
}

View File

@ -0,0 +1,24 @@
package com.suelec.permission.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class SysRolePermission implements Serializable {
private String id;
private String roleId;
private String permissionId;
private Date createTime;
}

View File

@ -0,0 +1,46 @@
package com.suelec.permission.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class SysUser implements Serializable {
private String id;
private String username;
private String password;
private String phone;
private String realName;
private String nickName;
private String email;
private Integer status;
private Integer sex;
private Integer deleted;
private String createId;
private String updateId;
private Integer createWhere;
private Date createTime;
private Date updateTime;
}

View File

@ -0,0 +1,18 @@
package com.suelec.permission.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class SysUserRole implements Serializable {
private String id;
private String userId;
private String roleId;
private Date createTime;
}

View File

@ -0,0 +1,238 @@
package com.suelec.permission.pojo;
import java.math.BigDecimal;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
*
*
* @author xianing
* @email 1042449477@qq.com
* @date 2023-08-09 16:41:39
*/
@Data
public class Tuser implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private Integer folk;
/**
*
*/
private Integer status;
/**
*
*/
private String slabs;
/**
*
*/
private Long id;
/**
*
*/
private String regname;
/**
*
*/
private String name;
/**
*
*/
private String password;
/**
*
*/
private Integer sex;
/**
*
*/
private String learn;
/**
*
*/
private Integer businesscategory;
/**
*
*/
private Long business;
/**
*
*/
private Long techgrade;
/**
*
*/
private Long techcategory;
/**
*
*/
private String photo;
/**
*
*/
private Date birthday;
/**
*
*/
private Integer certificatetype;
/**
*
*/
private String usercode;
/**
*
*/
private String certificatecode;
/**
*
*/
private Date workdate;
/**
*
*/
private String academy;
/**
*
*/
private String major;
/**
*
*/
private String degree;
/**
*
*/
private String phone;
/**
*
*/
private String email;
/**
*
*/
private String tcomment;
/**
*
*/
private Long reservedint;
/**
*
*/
private Long reservedint1;
/**
*
*/
private BigDecimal reserveddouble;
/**
*
*/
private String properties;
/**
*
*/
private String groupids;
/**
*
*/
private Date enterbankdate;
/**
*
*/
private Long corpid;
/**
*
*/
private Date syndate;
/**
*
*/
private String userCode;
/**
*
*/
private Integer level;
/**
*
*/
private Long worktype;
/**
*
*/
private Date syncdate;
/**
*
*/
private Integer isndg;
/**
*
*/
private Integer subuniv;
/**
*
*/
private String jobnumber;
/**
*
*/
private String tysfrz;
/**
*
*/
private Integer istysfrz;
/**
*
*/
private Long zgzt;
/**
*
*/
private Long cpid;
/**
*
*/
private String hrUserid;
/**
*
*/
private Integer userType;
/**
*
*/
private String zyjszg;
/**
*
*/
private Date modifyTime;
/**
*
*/
private Date createTime;
/**
*
*/
private String sysUserType;
/**
*
*/
private String groupNames;
/**
*
*/
private String flag;
/**
*
*/
private Date beginTime;
/**
*
*/
private Date endTime;
}

View File

@ -0,0 +1,46 @@
package com.suelec.permission.serializer;
import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/** redis 序列化策略
* @ClassName: MyStringRedisSerializer
*/
public class MyStringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
public MyStringRedisSerializer() {
this(StandardCharsets.UTF_8);
}
public MyStringRedisSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}
@Override
public String deserialize(byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
@Override
public byte[] serialize(Object object) {
if (object == null) {
return new byte[0];
}
if(object instanceof String){
return object.toString().getBytes(charset);
}else {
String string = JSON.toJSONString(object);
return string.getBytes(charset);
}
}
}

View File

@ -0,0 +1,14 @@
package com.suelec.permission.service;
import com.suelec.permission.utils.Response;
public interface HomeService {
/**
* 获取首页数据用户名称权限菜单
* @param userId
* @return
*/
Response getHome(String userId);
}

View File

@ -0,0 +1,25 @@
package com.suelec.permission.service;
import com.suelec.permission.pojo.SysLog;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LogPageReqVo;
import com.suelec.permission.vo.resp.PageVo;
import java.util.List;
public interface LogService {
/**
* 分页与条件查询所有数据
* @param logPageReqVo
* @return
*/
Response<PageVo<SysLog>> pageInfo(LogPageReqVo logPageReqVo);
/**
* 删除日志
* @param logIds
* @return
*/
Response<String> deletedLog(List<String> logIds);
}

View File

@ -0,0 +1,59 @@
package com.suelec.permission.service;
import com.suelec.permission.pojo.SysPermission;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.PermissionAddReqVo;
import com.suelec.permission.vo.req.PermissionUpdateReqVo;
import com.suelec.permission.vo.resp.PermissionRespNodeTreeVo;
import com.suelec.permission.vo.resp.PermissionRespNodeVo;
import java.util.List;
public interface PermissionService {
/**
* 用户id查询用户拥有的权限菜单列表
* @param userId
* @return
*/
List<PermissionRespNodeVo> permissionTreeListByUserId(String userId);
/**查询所有权限列表表格展示
* 树形表格结果数据组装
* @return
*/
List<SysPermission> selectAll();
/**
* 添加权限的上级选择权限树结构展示递归
* @return
*/
Response<List<PermissionRespNodeTreeVo>> selectAllMenuByTree();
/**
* 新增权限
* @param permissionAddReqVO
* @return
*/
Response addPermission(PermissionAddReqVo permissionAddReqVO);
/**
* 获取所有权限包括按钮角色添加/编辑/分配权限时用到的结果数据
* @return
*/
List<PermissionRespNodeVo> selectAllTree();
/**
* 更新权限
* @param permissionUpdateReqVo
* @return
*/
Response<String> updatePermission(PermissionUpdateReqVo permissionUpdateReqVo);
/**
* 删除菜单权限
* @param permissionId
* @return
*/
Response<String> deletedPermission(String permissionId);
}

View File

@ -0,0 +1,815 @@
package com.suelec.permission.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: RedisService
* @Version: 0.0.1
*/
@Service
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
/** -------------------key相关操作--------------------- */
/**
* 是否存在key
* @param key
* @return java.lang.Boolean
* @throws
*/
public Boolean hasKey(String key) {
if (null==key){
return false;
}
return redisTemplate.hasKey(key);
}
/**
* 删除key
* @param key
* @return Boolean 成功返回true 失败返回false
* @throws
*/
public Boolean delete(String key) {
if (null==key){
return false;
}
return redisTemplate.delete(key);
}
/**
* 批量删除key
* @param keys
* @return Long 返回成功删除key的数量
* @throws
*/
public Long delete(Collection<String> keys) {
return redisTemplate.delete(keys);
}
/**
* 设置过期时间
* @param key
 * @param timeout
 * @param unit
* @return java.lang.Boolean
* @throws
*/
public Boolean expire(String key, long timeout, TimeUnit unit) {
if (null==key||null==unit){
return false;
}
return redisTemplate.expire(key, timeout, unit);
}
/**
* 查找匹配的key
* @param pattern
* @return java.util.Set<java.lang.String>
* @throws
*/
public Set<String> keys(String pattern) {
if (null==pattern){
return null;
}
return redisTemplate.keys(pattern);
}
/**
* 移除 key 的过期时间key 将持久保持
* @param key
* @return java.lang.Boolean
* @throws
*/
public Boolean persist(String key) {
if (null==key){
return false;
}
return redisTemplate.persist(key);
}
/**
* 返回 key 的剩余的过期时间
* @param key
 * @param unit
* @return java.lang.Long key 不存在时返回 -2 key 存在但没有设置剩余生存时间时返回 -1 否则以秒为单位返回 key的剩余生存时间
* @throws
*/
public Long getExpire(String key, TimeUnit unit) {
if(null==key||null==unit){
throw new RuntimeException("key or TomeUnit 不能为空");
}
return redisTemplate.getExpire(key, unit);
}
//*************String相关数据类型***************************
/**
* 设置指定 key 的值
* @Author: 小霍
* @UpdateUser:
* @Version: 0.0.1
* @param key
* @param value
* @return void
* @throws
*/
public void set(String key, Object value) {
if(null==key||null==value){
return;
}
redisTemplate.opsForValue().set(key, value);
}
/**
* 设置key 的值 并设置过期时间
* @param key
* @param value
* @param time
* @param unit
* @return void
* @throws
*/
public void set(String key,Object value,long time,TimeUnit unit){
if(null==key||null==value||null==unit){
return;
}
redisTemplate.opsForValue().set(key,value,time,unit);
}
/**
* 设置key 的值 并设置过期时间
* key存在 不做操作返回false
* key不存在设置值返回true
* @param key
* @param value
* @param time
* @param unit
* @return java.lang.Boolean
* @throws
*/
public Boolean setifAbsen(String key,Object value,long time,TimeUnit unit){
if(null==key||null==value||null==unit){
throw new RuntimeException("kkey、value、unit都不能为空");
}
return redisTemplate.opsForValue().setIfAbsent(key,value,time,unit);
}
/**
* 获取指定Key的Value如果与该Key关联的Value不是string类型Redis将抛出异常
* 因为GET命令只能用于获取string Value如果该Key不存在返回null
* @param key
* @return java.lang.Object
* @throws
*/
public Object get(String key){
if(null==key){
return null;
}
return redisTemplate.opsForValue().get(key);
}
/**
* 很明显先get再set就说先获取key值对应的value然后再set 新的value
* @param key
 * @param value
* @return java.lang.Object
* @throws
*/
public Object getSet(String key,Object value){
if(null==key){
return null;
}
return redisTemplate.opsForValue().getAndSet(key,value);
}
/**
* 通过批量的key获取批量的value
* @param keys
* @return java.util.List<java.lang.Object>
* @throws
*/
public List<Object> mget(Collection<String> keys){
if(null==keys){
return Collections.emptyList();
}
return redisTemplate.opsForValue().multiGet(keys);
}
/**
* 将指定Key的Value原子性的增加increment如果该Key不存在其初始值为0在incrby之后其值为increment
* 如果Value的值不能转换为整型值如Hi该操作将执行失败并抛出相应异常操作成功则返回增加后的value值
* @param key
 * @param increment
* @return long
* @throws
*/
public long incrby(String key,long increment){
if(null==key){
throw new RuntimeException("key不能为空");
}
return redisTemplate.opsForValue().increment(key,increment);
}
/**
*
* 将指定Key的Value原子性的减少decrement如果该Key不存在其初始值为0
* 在decrby之后其值为-decrement如果Value的值不能转换为整型值
* 如Hi该操作将执行失败并抛出相应的异常操作成功则返回减少后的value值
* @param key
 * @param decrement
* @return java.lang.Long
* @throws
*/
public Long decrby(String key,long decrement){
if(null==key){
throw new RuntimeException("key不能为空");
}
return redisTemplate.opsForValue().decrement(key,decrement);
}
/**
* 如果该Key已经存在APPEND命令将参数Value的数据追加到已存在Value的末尾如果该Key不存在
* APPEND命令将会创建一个新的Key/Value返回追加后Value的字符串长度
* @param key
 * @param value
* @return java.lang.Integer
* @throws
*/
public Integer append(String key,String value){
if(key==null){
throw new RuntimeException("key不能为空");
}
return redisTemplate.opsForValue().append(key,value);
}
//****************** hash数据类型 *********************
/**
* 通过key field 获取指定的 value
* @param key
* @param field
* @return java.lang.Object
* @throws
*/
public Object hget(String key, Object field) {
if(null==key||null==field){
return null;
}
return redisTemplate.opsForHash().get(key,field);
}
/**
* 为指定的Key设定Field/Value对如果Key不存在该命令将创建新Key以用于存储参数中的Field/Value对
* 如果参数中的Field在该Key中已经存在则用新值覆盖其原有值
* 返回1表示新的Field被设置了新值0表示Field已经存在用新值覆盖原有值
* @param key
* @param field
* @param value
* @return
* @throws
*/
public void hset(String key, Object field, Object value) {
if(null==key||null==field){
return;
}
redisTemplate.opsForHash().put(key,field,value);
}
/**
* 判断指定Key中的指定Field是否存在返回true表示存在false表示参数中的Field或Key不存在
* @param key
* @param field
* @return java.lang.Boolean
* @throws
*/
public Boolean hexists(String key, Object field) {
if(null==key||null==field){
return false;
}
return redisTemplate.opsForHash().hasKey(key,field);
}
/**
* 从指定Key的Hashes Value中删除参数中指定的多个字段如果不存在的字段将被忽略
* 返回实际删除的Field数量如果Key不存在则将其视为空Hashes并返回0
* @param key
* @param fields
* @return java.lang.Long
* @throws
*/
public Long hdel(String key, Object... fields) {
if(null==key||null==fields||fields.length==0){
return 0L;
}
return redisTemplate.opsForHash().delete(key,fields);
}
/**
* 通过key获取所有的field和value
* @param key
* @return java.util.Map<java.lang.Object,java.lang.Object>
* @throws
*/
public Map<Object, Object> hgetall(String key) {
if(key==null){
return null;
}
return redisTemplate.opsForHash().entries(key);
}
/**
* 逐对依次设置参数中给出的Field/Value对如果其中某个Field已经存在则用新值覆盖原有值
* 如果Key不存在则创建新Key同时设定参数中的Field/Value
* @param key
* @param hash
* @return
* @throws
*/
public void hmset(String key, Map<String, Object> hash) {
if(null==key||null==hash){
return;
}
redisTemplate.opsForHash().putAll(key,hash);
}
/**
* 获取和参数中指定Fields关联的一组Values其返回顺序等同于Fields的请求顺序
* 如果请求的Field不存在其值对应的value为null
* @param key
* @param fields
* @return java.util.List<java.lang.Object>
* @throws
*/
public List<Object> hmget(String key, Collection<Object> fields) {
if(null==key||null==fields){
return null;
}
return redisTemplate.opsForHash().multiGet(key,fields);
}
/**
* 对应key的字段自增相应的值
* @param key
 * @param field
 * @param increment
* @return java.lang.Long
* @throws
*/
public Long hIncrBy(String key,Object field,long increment){
if (null==key||null==field){
throw new RuntimeException("key or field 不能为空");
}
return redisTemplate.opsForHash().increment(key,field,increment);
}
//*************** List数据类型 ***************
/**
* 向列表左边添加元素如果该Key不存在该命令将在插入之前创建一个与该Key关联的空链表之后再将数据从链表的头部插入
* 如果该键的Value不是链表类型该命令将将会抛出相关异常操作成功则返回插入后链表中元素的数量
* @param key
* @param strs 可以使一个string 也可以使string数组
* @return java.lang.Long 返回操作的value个数
* @throws
*/
public Long lpush(String key, Object... strs) {
if(null==key){
return 0L;
}
return redisTemplate.opsForList().leftPushAll(key,strs);
}
/**
* 向列表右边添加元素如果该Key不存在该命令将在插入之前创建一个与该Key关联的空链表之后再将数据从链表的尾部插入
* 如果该键的Value不是链表类型该命令将将会抛出相关异常操作成功则返回插入后链表中元素的数量
* @param key
* @param strs 可以使一个string 也可以使string数组
* @return java.lang.Long 返回操作的value个数
* @throws
*/
public Long rpush(String key, Object... strs) {
if(null==key){
return 0L;
}
return redisTemplate.opsForList().rightPushAll(key,strs);
}
/**
* 返回并弹出指定Key关联的链表中的第一个元素即头部元素如果该Key不存在
* 返回nilLPOP命令执行两步操作第一步是将列表左边的元素从列表中移除第二步是返回被移除的元素值
* @param key
* @return java.lang.Object
* @throws
*/
public Object lpop(String key) {
if(null==key){
return null;
}
return redisTemplate.opsForList().leftPop(key);
}
/**
* 返回并弹出指定Key关联的链表中的最后一个元素即头部元素如果该Key不存在返回nil
* RPOP命令执行两步操作第一步是将列表右边的元素从列表中移除第二步是返回被移除的元素值
* @param key
* @return java.lang.Object
* @throws
*/
public Object rpop(String key) {
if(null==key){
return null;
}
return redisTemplate.opsForList().rightPop(key);
}
/**
*该命令的参数start和end都是0-based即0表示链表头部(leftmost)的第一个元素
* 其中start的值也可以为负值-1将表示链表中的最后一个元素即尾部元素-2表示倒数第二个并以此类推
* 该命令在获取元素时start和end位置上的元素也会被取出如果start的值大于链表中元素的数量
* 空链表将会被返回如果end的值大于元素的数量该命令则获取从start(包括start)开始链表中剩余的所有元素
* Redis的列表起始索引为0显然LRANGE numbers 0 -1 可以获取列表中的所有元素返回指定范围内元素的列表
* @param key
* @param start
* @param end
* @return java.util.List<java.lang.Object>
* @throws
*/
public List<Object> lrange(String key, long start, long end) {
if(null==key){
return null;
}
return redisTemplate.opsForList().range(key,start,end);
}
/**
* 让列表只保留指定区间内的元素不在指定区间之内的元素都将被删除
* 下标 0 表示列表的第一个元素 1 表示列表的第二个元素以此类推
* 你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
* @param key
* @param start
* @param end
* @return
* @throws
*/
public void ltrim(String key, long start, long end) {
if(null==key){
return;
}
redisTemplate.opsForList().trim(key,start,end);
}
/**
* 该命令将返回链表中指定位置(index)的元素index是0-based表示从头部位置开始第index的元素
* 如果index为-1表示尾部元素如果与该Key关联的不是链表该命令将返回相关的错误信息 如果超出index返回这返回nil
* @param key
* @param index
* @return java.lang.Object
* @throws
*/
public Object lindex(String key, long index) {
if(null==key){
return null;
}
return redisTemplate.opsForList().index(key,index);
}
/**
* 返回指定Key关联的链表中元素的数量如果该Key不存在则返回0如果与该Key关联的Value的类型不是链表则抛出相关的异常
* @param key
* @return java.lang.Long
* @throws
*/
public Long llen(String key) {
if(null==key){
return 0L;
}
return redisTemplate.opsForList().size(key);
}
//*************** Set数据类型 *************
/**
* 如果在插入的过程用参数中有的成员在Set中已经存在该成员将被忽略而其它成员仍将会被正常插入
* 如果执行该命令之前该Key并不存在该命令将会创建一个新的Set此后再将参数中的成员陆续插入返回实际插入的成员数量
* @param key
 * @param members 可以是一个String 也可以是一个String数组
* @return java.lang.Long 添加成功的个数
* @throws
*/
public Long sadd(String key, Object... members) {
if (null==key){
return 0L;
}
return redisTemplate.opsForSet().add(key, members);
}
/**
* 返回Set中成员的数量如果该Key并不存在返回0
* @param key
* @return java.lang.Long
* @throws
*/
public Long scard(String key) {
if (null==key){
return 0L;
}
return redisTemplate.opsForSet().size(key);
}
/**
* 判断参数中指定成员是否已经存在于与Key相关联的Set集合中返回true表示已经存在false表示不存在或该Key本身并不存在
* @param key
 * @param member
* @return java.lang.Boolean
* @throws
*/
public Boolean sismember(String key, Object member) {
if (null==key){
return false;
}
return redisTemplate.opsForSet().isMember(key,member);
}
/**
* 和SPOP一样随机的返回Set中的一个成员不同的是该命令并不会删除返回的成员
* @param key
* @return java.lang.String
* @throws
*/
public Object srandmember(String key) {
if (null==key){
return null;
}
return redisTemplate.opsForSet().randomMember(key);
}
/**
* 和SPOP一样随机的返回Set中的一个成员不同的是该命令并不会删除返回的成员
* 还可以传递count参数来一次随机获得多个元素根据count的正负不同具体表现也不同
* 当count 为正数时SRANDMEMBER 会随机从集合里获得count个不重复的元素
* 如果count的值大于集合中的元素个数则SRANDMEMBER 会返回集合中的全部元素
* 当count为负数时SRANDMEMBER 会随机从集合里获得|count|个的元素如果|count|大与集合中的元素
* 就会返回全部元素不够的以重复元素补齐如果key不存在则返回nil
* @param key
 * @param count
* @return java.util.List<java.lang.String>
* @throws
*/
public List<Object> srandmember(String key,int count) {
if(null==key){
return null;
}
return redisTemplate.opsForSet().randomMembers(key,count);
}
/**
* 通过key随机删除一个set中的value并返回该值
* @param key
* @return java.lang.String
* @throws
*/
public Object spop(String key) {
if (null==key){
return null;
}
return redisTemplate.opsForSet().pop(key);
}
/**
* 通过key获取set中所有的value
* @param key
* @return java.util.Set<java.lang.String>
* @throws
*/
public Set<Object> smembers(String key) {
if (null==key){
return null;
}
return redisTemplate.opsForSet().members(key);
}
/**
* 从与Key关联的Set中删除参数中指定的成员不存在的参数成员将被忽略
* 如果该Key并不存在将视为空Set处理返回从Set中实际移除的成员数量如果没有则返回0
* @param key
* @param members
* @return java.lang.Long
* @throws
*/
public Long srem(String key, Object... members) {
if (null==key){
return 0L;
}
return redisTemplate.opsForSet().remove(key,members);
}
/**
* 将元素value从一个集合移到另一个集合
* @param srckey
* @param dstkey
* @param member
* @return java.lang.Long
* @throws
*/
public Boolean smove(String srckey, String dstkey, Object member) {
if (null==srckey||null==dstkey){
return false;
}
return redisTemplate.opsForSet().move(srckey,member,dstkey);
}
/**
* 获取两个集合的并集
* @param key
* @param otherKeys
* @return java.util.Set<java.lang.Object> 返回两个集合合并值
* @throws
*/
public Set<Object> sUnion(String key, String otherKeys) {
if (null==key||otherKeys==null){
return null;
}
return redisTemplate.opsForSet().union(key, otherKeys);
}
//********** Sorted Set 数据类型 ********************
/**
*添加参数中指定的所有成员及其分数到指定key的Sorted Set中在该命令中我们可以指定多组score/member作为参数
* 如果在添加时参数中的某一成员已经存在该命令将更新此成员的分数为新值同时再将该成员基于新值重新排序
* 如果键不存在该命令将为该键创建一个新的Sorted Set Value并将score/member对插入其中
* @param key
* @param score
* @param member
* @return java.lang.Long
* @throws
*/
public Boolean zadd(String key, double score, Object member) {
if (null==key){
return false;
}
return redisTemplate.opsForZSet().add(key,member,score);
}
/**
* 该命令将移除参数中指定的成员其中不存在的成员将被忽略
* 如果与该Key关联的Value不是Sorted Set相应的错误信息将被返回 如果操作成功则返回实际被删除的成员数量
* @param key
* @param members 可以使一个string 也可以是一个string数组
* @return java.lang.Long
* @throws
*/
public Long zrem(String key, Object... members) {
if(null==key||null==members){
return 0L;
}
return redisTemplate.opsForZSet().remove(key,members);
}
/**
* 返回Sorted Set中的成员数量如果该Key不存在返回0
* @param key
* @return java.lang.Long
* @throws
*/
public Long zcard(String key) {
if (null==key){
return 0L;
}
return redisTemplate.opsForZSet().size(key);
}
/**
* 该命令将为指定Key中的指定成员增加指定的分数如果成员不存在该命令将添加该成员并假设其初始分数为0
* 此后再将其分数加上increment如果Key不存在该命令将创建该Key及其关联的Sorted Set
* 并包含参数指定的成员其分数为increment参数如果与该Key关联的不是Sorted Set类型
* 相关的错误信息将被返回如果不报错则以串形式表示的新分数
* @param key
* @param score
* @param member
* @return java.lang.Double
* @throws
*/
public Double zincrby(String key, double score, Object member) {
if (null==key){
throw new RuntimeException("key 不能为空");
}
return redisTemplate.opsForZSet().incrementScore(key,member,score);
}
/**
* 该命令用于获取分数(score)在min和max之间的成员数量
* min=<score<=max如果加上了(着表明是开区间例如zcount key (min max 表示min<score=<max
* 同理zcount key min (max 则表明(min=<score<max) 返回指定返回数量
* @param key
* @param min
* @param max
* @return java.lang.Long
* @throws
*/
public Long zcount(String key, double min, double max) {
if (null==key){
return 0L;
}
return redisTemplate.opsForZSet().count(key, min, max);
}
/**
* Sorted Set中的成员都是按照分数从低到高的顺序存储该命令将返回参数中指定成员的位置值
* 其中0表示第一个成员它是Sorted Set中分数最低的成员 如果该成员存在则返回它的位置索引值否则返回nil
* @param key
* @param member
* @return java.lang.Long
* @throws
*/
public Long zrank(String key, Object member) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().rank(key,member);
}
/**
* 如果该成员存在以字符串的形式返回其分数否则返回null
* @param key
* @param member
* @return java.lang.Double
* @throws
*/
public Double zscore(String key, Object member) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().score(key,member);
}
/**
* 该命令返回顺序在参数start和stop指定范围内的成员这里start和stop参数都是0-based即0表示第一个成员-1表示最后一个成员如果start大于该Sorted
* Set中的最大索引值或start > stop此时一个空集合将被返回如果stop大于最大索引值
* 该命令将返回从start到集合的最后一个成员如果命令中带有可选参数WITHSCORES选项
* 该命令在返回的结果中将包含每个成员的分数值如value1,score1,value2,score2...
* @param key
* @param min
* @param max
* @return java.util.Set<java.lang.String> 指定区间内的有序集成员的列表
* @throws
*/
public Set<Object> zrange(String key, long min, long max) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().range(key, min, max);
}
/**
* 该命令的功能和ZRANGE基本相同唯一的差别在于该命令是通过反向排序获取指定位置的成员
* 即从高到低的顺序如果成员具有相同的分数则按降序字典顺序排序
* @param key
* @param start
* @param end
* @return java.util.Set<java.lang.String>
* @throws
*/
public Set<Object> zReverseRange(String key, long start, long end) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().reverseRange(key, start, end);
}
/**
* 该命令将返回分数在min和max之间的所有成员即满足表达式min <= score <= max的成员
* 其中返回的成员是按照其分数从低到高的顺序返回如果成员具有相同的分数
* 则按成员的字典顺序返回可选参数LIMIT用于限制返回成员的数量范围
* 可选参数offset表示从符合条件的第offset个成员开始返回同时返回count个成员
* 可选参数WITHSCORES的含义参照ZRANGE中该选项的说明*最后需要说明的是参数中min和max的规则可参照命令ZCOUNT
* @param key
* @param max
* @param min
* @return java.util.Set<java.lang.String>
* @throws
*/
public Set<Object> zrangebyscore(String key, double min, double max) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().rangeByScore(key, min, max);
}
/**
* 该命令除了排序方式是基于从高到低的分数排序之外其它功能和参数含义均与ZRANGEBYSCORE相同
* 需要注意的是该命令中的min和max参数的顺序和ZRANGEBYSCORE命令是相反的
* @param key
* @param max
* @param min
* @return java.util.Set<java.lang.String>
* @throws
*/
public Set<Object> zrevrangeByScore(String key, double min, double max) {
if (null==key){
return null;
}
return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
}
}

View File

@ -0,0 +1,39 @@
package com.suelec.permission.service;
import com.suelec.permission.vo.req.RolePermissionOperationReqVo;
import java.util.List;
public interface RolePermissionService {
/**
* 插入角色权限关联表数据
*/
void addRolePermission(RolePermissionOperationReqVo operationReqVo);
/**
* 通过权限 id 查询所有的角色 id
* @param permissionId
* @return
*/
List<String> getRoleIdsByPermissionId(String permissionId);
/**
* 通过权限id删除相关角色和该菜单权限的关联表信息
* @param permissionId
*/
int removeRoleByPermissionId(String permissionId);
/**
* 通过角色id查询拥有的权限id
* @param roleId
*/
List<String> getPermissionIdsByRoleId(String roleId);
/**
* 通过角色id删除权限id
* @param roleId
* @return
*/
int removeByRoleId(String roleId);
}

View File

@ -0,0 +1,62 @@
package com.suelec.permission.service;
import com.suelec.permission.pojo.SysRole;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.RolePageReqVo;
import com.suelec.permission.vo.req.RoleReqVo;
import com.suelec.permission.vo.req.RoleUpdateReqVo;
import com.suelec.permission.vo.resp.PageVo;
import java.util.List;
import java.util.Set;
public interface RoleService {
/**
* 角色管理分页数据
* @return
*/
Response<PageVo> pageInfoRoles(RolePageReqVo rolePageReqVo);
/**
* 新增角色
* @param roleReqVo
* @return
*/
Response<String> createRole(RoleReqVo roleReqVo);
/**
* 查询所有权限
* @return
*/
List<SysRole> selectAll();
/**
* 获取角色详情数据
* @param roleId
* @return
*/
Response<Set<String>> detailInfo(String roleId);
/**
* 更新角色信息
* @param roleUpdateReqVo
* @return
*/
Response<String> updateRole(RoleUpdateReqVo roleUpdateReqVo);
/**
* 删除角色信息
* @param roleId
* @return
*/
Response<String> deletedRole(String roleId);
/**
* 更新角色状态
* @param roleId
* @param status
* @return
*/
Response<String> updateRoleStatus(String roleId, Integer status);
}

View File

@ -0,0 +1,41 @@
package com.suelec.permission.service;
import com.suelec.permission.vo.req.UserOwnRoleReqVo;
import java.util.List;
public interface UserRoleService {
/**
* 根据用户id 查询用户拥有的角色数据接口
*/
List<String> getRoleIdsByUserId(String userId);
/**
* 更新用户角色
* @param userOwnRoleReqVo
* @return
*/
void addUserRoleInfo(UserOwnRoleReqVo userOwnRoleReqVo);
/**
* 通过角色 id 集合查询所有的用户 id
* @param roleIdsByPermissionId
* @return
*/
List<String> getUserIdsByRoleIds(List<String> roleIdsByPermissionId);
/**
* 通过 单个角色id 查询所有的用户ids
* @param roleId
* @return
*/
List<String> getUserIdsByRoleId(String roleId);
/**
* 通过角色id删除用户id
* @param roleId
* @return
*/
int removeUseIdsrRoleId(String roleId);
}

View File

@ -0,0 +1,108 @@
package com.suelec.permission.service;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LoginReqVo;
import com.suelec.permission.vo.req.UserAddReqVo;
import com.suelec.permission.vo.req.UserOwnRoleReqVo;
import com.suelec.permission.vo.req.UserPageReqVo;
import com.suelec.permission.vo.req.UserUpdateDetailInfoReqVo;
import com.suelec.permission.vo.req.UserUpdatePasswordReqVo;
import com.suelec.permission.vo.req.UserUpdateReqVo;
import com.suelec.permission.vo.resp.LoginRespVo;
import com.suelec.permission.vo.resp.PageVo;
import com.suelec.permission.vo.resp.UserOwnRoleRespVo;
import com.suelec.permission.vo.resp.UserRespVo;
import com.suelec.permission.vo.resp.UserTableRespVo;
import java.util.List;
public interface UserService {
/**
* 登陆
* @param loginReqVo
* @return
*/
Response<LoginRespVo> login(LoginReqVo loginReqVo);
/**
* 退出登陆
* @param accessToken
* @return
*/
Response<String> logout(String accessToken);
/**
* 分页查询用户包括搜索条件
* @param userPageReqVo
* @return
*/
Response<PageVo<UserTableRespVo>> pageInfo(UserPageReqVo userPageReqVo);
/**
* 新增用户
* @param userAddReqVo
* @return
*/
Response<String> addUser(UserAddReqVo userAddReqVo);
/**
* 查询用户拥有的角色数据接口
* @param userId
* @return
*/
Response<UserOwnRoleRespVo> getUserOwnRole(String userId);
/**
* 更新用户角色
* @param vo
* @return
*/
Response<String> setUserOwnRole(UserOwnRoleReqVo vo);
/**
* 更新用户信息
* @param userUpdateReqVo
* @param operationId 操作人
* @return
*/
Response<String> updateUserInfo(UserUpdateReqVo userUpdateReqVo, String operationId);
/**
* 批量/删除用户接口
* @param list
* @param operationId 操作人
* @return
*/
Response<String> deletedUsers(List<String> list, String operationId);
/**
* 获取个人资料编辑信息
* @param userId
* @return
*/
Response<UserRespVo> detailInfo(String userId);
/**
* 保存个人信息接口
* @param updateDetailInfoReqVo
* @param userId
* @return
*/
Response<String> userUpdateDetailInfo(UserUpdateDetailInfoReqVo updateDetailInfoReqVo, String userId);
/**
* 修改个人密码
* @param userUpdatePasswordReqVo
* @param accessToken
* @return
*/
Response<String> userUpdatePassword(UserUpdatePasswordReqVo userUpdatePasswordReqVo, String accessToken);
/**
* 重置用户密码
* @param userId
* @return
*/
Response<String> resetUpdatePassword(String userId);
}

View File

@ -0,0 +1,48 @@
package com.suelec.permission.service.impl;
import com.suelec.permission.dao.SysUserDao;
import com.suelec.permission.pojo.SysUser;
import com.suelec.permission.service.HomeService;
import com.suelec.permission.service.PermissionService;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.resp.HomeRespVo;
import com.suelec.permission.vo.resp.PermissionRespNodeVo;
import com.suelec.permission.vo.resp.UserRespVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class HomeServiceImpl implements HomeService {
@Autowired
private SysUserDao sysUserDao;
@Autowired
private PermissionService permissionService;
/**
* 获取首页数据用户名称权限菜单
* @param userId
* @return
*/
@Override
public Response getHome(String userId) {
//String meuns = "[{\"children\":[{\"children\":[{\"children\":[{\"children\":[{\"children\":[],\"id\":\"6\",\"title\":\"五级类目5-6\",\"url\":\"string\"}],\"id\":\"5\",\"title\":\"四级类目4- 5\",\"url\":\"string\"}],\"id\":\"4\",\"title\":\"三级类目3- 4\",\"url\":\"string\"}],\"id\":\"3\",\"title\":\"二级类目2- 3\",\"url\":\"string\"}],\"id\":\"1\",\"title\":\"类目1\",\"url\":\"string\"},{\"children\": [],\"id\":\"2\",\"title\":\"类目2\",\"url\":\"string\"}]";
//String meuns = "[{\"children\":[{\"children\":[],\"id\":\"6\",\"title\":\"五级类目5-6\",\"url\":\"/index/menus\"}],\"id\":\"1\",\"title\":\"类目1\",\"url\":\"string\"},{\"children\": [],\"id\":\"2\",\"title\":\"类目2\",\"url\":\"string\"}]";
//List<PermissionRespNodeVo> permissionRespNodeVos = JSON.parseArray(meuns, PermissionRespNodeVo.class);
// 权限菜单
List<PermissionRespNodeVo> permissionRespNodeVos = permissionService.permissionTreeListByUserId(userId);
// 用户信息
SysUser sysUser = sysUserDao.selectByPrimaryKey(userId);
UserRespVo userRespVo = new UserRespVo();
if (sysUser != null){
BeanUtils.copyProperties(sysUser,userRespVo);
}
HomeRespVo homeRespVo = new HomeRespVo();
homeRespVo.setMenus(permissionRespNodeVos);
homeRespVo.setUserInfo(userRespVo);
return Response.success(homeRespVo);
}
}

View File

@ -0,0 +1,50 @@
package com.suelec.permission.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.suelec.permission.dao.SysLogDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysLog;
import com.suelec.permission.service.LogService;
import com.suelec.permission.utils.PageUtil;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LogPageReqVo;
import com.suelec.permission.vo.resp.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class LogServiceLmpl implements LogService {
@Autowired
private SysLogDao sysLogDao;
/**
* 分页与条件查询所有数据
* @param logPageReqVo
* @return
*/
@Override
public Response<PageVo<SysLog>> pageInfo(LogPageReqVo logPageReqVo) {
PageHelper.startPage(logPageReqVo.getPageNum(),logPageReqVo.getPageSize());
List<SysLog> sysLogs = sysLogDao.selectAll(logPageReqVo);
return Response.success(PageUtil.getPageVo(new PageInfo<SysLog>(sysLogs)));
}
/**
* 删除日志
* @param logIds
* @return
*/
@Override
public Response<String> deletedLog(List<String> logIds) {
int resultCount = sysLogDao.batchDeletedLog(logIds);
if (resultCount == 0){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
}

View File

@ -0,0 +1,332 @@
package com.suelec.permission.service.impl;
import com.suelec.permission.config.TokenConfig;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.dao.SysPermissionDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysPermission;
import com.suelec.permission.service.PermissionService;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.service.RolePermissionService;
import com.suelec.permission.service.UserRoleService;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.PermissionAddReqVo;
import com.suelec.permission.vo.req.PermissionUpdateReqVo;
import com.suelec.permission.vo.resp.PermissionRespNodeTreeVo;
import com.suelec.permission.vo.resp.PermissionRespNodeVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class PermissionServiceImpl implements PermissionService {
private static Logger logger = LoggerFactory.getLogger(PermissionServiceImpl.class);
@Autowired
private SysPermissionDao sysPermissionDao;
@Autowired
private IdWorker idWorker;
@Autowired
private RolePermissionService rolePermissionService;
@Autowired
private UserRoleService userRoleService;
@Autowired
private RedisService redisService;
@Autowired
private TokenConfig tokenConfig;
/**
* 用户id查询用户拥有的权限菜单列表
* @param userId
* @return
*/
@Override
public List<PermissionRespNodeVo> permissionTreeListByUserId(String userId) {
List<SysPermission> permissionList = sysPermissionDao.getPermissionByUserId(userId);
return getTree(permissionList,true);
}
/**
* 查询所有权限列表树形表格结果数据展示
* 树形表格结果数据组装
* @return
*/
public List<SysPermission> selectAll() {
List<SysPermission> sysPermissions = sysPermissionDao.selectAll();
if (!sysPermissions.isEmpty()){
for (SysPermission sysPermission : sysPermissions){
for (SysPermission permission : sysPermissions){
if(StringUtils.isNotBlank(sysPermission.getPid()) && StringUtils.isNotBlank(permission.getId()) && StringUtils.equals(sysPermission.getPid(),permission.getId())){
sysPermission.setPidName(permission.getName());
break;
}
}
}
}
return sysPermissions;
}
/**
* 添加权限的上级选择权限树结构展示递归不需要展示到按钮
* @return
*/
@Override
public Response<List<PermissionRespNodeTreeVo>> selectAllMenuByTree() {
// 设置一个最顶级的吗默认选项
// vue返回数据
List<SysPermission> list = sysPermissionDao.selectAll();
List<PermissionRespNodeTreeVo> result = new ArrayList<>();
PermissionRespNodeTreeVo respNodeVoDefault = new PermissionRespNodeTreeVo();
respNodeVoDefault.setId("0");
respNodeVoDefault.setTitle("顶级菜单");
respNodeVoDefault.setLevel(0);
result.add(respNodeVoDefault);
result.addAll(setPermissionLevelTree(list,String.valueOf(0),1));
return Response.success(result);
}
// 递归设置级别用于 添加/编辑 所属菜单树结构数据
private List<PermissionRespNodeTreeVo> setPermissionLevelTree(List<SysPermission> permissions,String parentId,int level){
List<PermissionRespNodeTreeVo> list = new ArrayList<>();
for (SysPermission permission : permissions){
if (permission.getType().intValue() != 3 && permission.getPid().equals(parentId)){
PermissionRespNodeTreeVo respNodeVo = new PermissionRespNodeTreeVo();
respNodeVo.setId(permission.getId());
respNodeVo.setTitle(permission.getTitle());
respNodeVo.setLevel(level);
list.add(respNodeVo);
list.addAll(setPermissionLevelTree(permissions,permission.getId(),level+1));
}
}
return list;
}
//==================== start 递归筛选 目录与菜单权限 排除按钮 type = 3 ====================
/**
* type=true 递归遍历到菜单
* type=false 递归遍历到按钮
* @param permissionList
* @param type
* @return
*/
private List<PermissionRespNodeVo> getTree(List<SysPermission> permissionList,boolean type){
// 无父级 pid 默认 0
return _getTree(permissionList,"0",type);
}
private List<PermissionRespNodeVo> _getTree(List<SysPermission> permissionList,String id,boolean type){
List<PermissionRespNodeVo> list = new ArrayList<>();
if (null == permissionList || permissionList.isEmpty()){
return list;
}
for (SysPermission permission : permissionList){
if (permission.getPid().equals(id)){
// 遍历到按钮 不遍历到按钮 都会执行
if (type || (!type && permission.getType().intValue() != 3)){
PermissionRespNodeVo respNodeVo = new PermissionRespNodeVo();
respNodeVo.setId(permission.getId());
respNodeVo.setTitle(permission.getTitle());
respNodeVo.setIcon(permission.getIcon());
respNodeVo.setPath(permission.getUrl());
respNodeVo.setName(permission.getName());
respNodeVo.setMenu(permission.getType()!=3);
respNodeVo.setChildren(_getTree(permissionList,permission.getId(),type));
list.add(respNodeVo);
}/*else if (type){
PermissionRespNodeVo respNodeVo = new PermissionRespNodeVo();
respNodeVo.setId(permission.getId());
respNodeVo.setTitle(permission.getName());
respNodeVo.setUrl(permission.getUrl());
respNodeVo.setChildren(_getTree(permissionList,permission.getId(),type));
list.add(respNodeVo);
}*/
}
}
return list;
}
//==================== end 递归筛选 目录与菜单权限 排除按钮 type = 3 ====================
/**
* 新增权限
* @param permissionAddReqVo
* @return
*/
@Override
public Response addPermission(PermissionAddReqVo permissionAddReqVo) {
// 验证表单数据
SysPermission permission = new SysPermission();
BeanUtils.copyProperties(permissionAddReqVo,permission);
verifyForm(permission);
permission.setId(String.valueOf(idWorker.nextId()));
permission.setCreateTime(new Date());
int result = sysPermissionDao.insertSelective(permission);
if (result != 1){
return Response.error(ResponseCode.OPERATION_ERROR.getMessage());
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 更新权限
* @param permissionUpdateReqVo
* @return
*/
@Override
public Response<String> updatePermission(PermissionUpdateReqVo permissionUpdateReqVo) {
// 1.验证表单数据
SysPermission permission = new SysPermission();
BeanUtils.copyProperties(permissionUpdateReqVo,permission);
verifyForm(permission);
SysPermission sysPermission = sysPermissionDao.selectByPrimaryKey(permission.getId());
if (sysPermission == null){
logger.info("传入的id在数据库中不存在,{}",permissionUpdateReqVo);
throw new BusinessException(ResponseCode.DATA_ERROR);
}
// 2.验证 所属菜单是否发生了变化
if (!sysPermission.getPid().equals(permissionUpdateReqVo.getPid())){
// 目录 菜单 按钮 菜单有子级按钮则不能吧当前菜单更新为按钮类型
// 所属菜单发生了变化要校验该权限是否存在子集
int resultCount = sysPermissionDao.selectChild(permissionUpdateReqVo.getId());
if (resultCount > 0){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_UPDATE);
}
}
// 3.更新菜单信息
permission.setUpdateTime(new Date());
int updateResultCount = sysPermissionDao.updateByPrimaryKeySelective(permission);
if (updateResultCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
// TODO: vue方式 此处待处理
// 4.判断授权标识符是否发生了变化***注意如发生变化需要更新与权限菜单相关的用户在 redis 中的状态
if (!sysPermission.getPerms().equals(permissionUpdateReqVo.getPerms())){
// 通过权限 id 查询所有的角色 id
List<String> roleIdsByPermissionId = rolePermissionService.getRoleIdsByPermissionId(permissionUpdateReqVo.getId());
if (roleIdsByPermissionId != null && !roleIdsByPermissionId.isEmpty()){
// 通过角色 id 查询所有的用户 id
List<String> userIdsByRoleIds = userRoleService.getUserIdsByRoleIds(roleIdsByPermissionId);
if (userIdsByRoleIds!=null && !userIdsByRoleIds.isEmpty()){
for (String userId :userIdsByRoleIds){
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+userId,userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
}
}
}
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
// 验证参数
private void verifyForm(SysPermission permissionReqVo){
// 默认顶级 无父级 pid 默认 0
//操作后的菜单类型是目录的时候 父级必须为目录
//操作后的菜单类型是菜单的时候父类必须为目录类型
//操作后的菜单类型是按钮的时候 父类必须为菜单类型
Integer type = permissionReqVo.getType();
String pid = permissionReqVo.getPid();
if (null != type && StringUtils.isNotBlank(pid)){
SysPermission permission = sysPermissionDao.selectByPrimaryKey(pid);
if (type == 1){
if (permission != null && permission.getType() > 1){// 父级 只能为 无父级/目录类型 0 / 1
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
}
}else if (type == 2) {// 父级 只能为目录类型 1
if ("0".equals(pid) || (permission != null && permission.getType() != 1)){// 父级 只能为目录类型 1
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_MENU_ERROR);
}
if (StringUtils.isBlank(permissionReqVo.getUrl())){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
}
}else if (type == 3) {// 父级 只能为菜单类型 2
if ("0".equals(pid) || (permission != null && permission.getType() != 2)){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_BTN_ERROR);
}
if(StringUtils.isEmpty(permissionReqVo.getPerms())){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_PERMS_NULL);
}
if(StringUtils.isEmpty(permissionReqVo.getUrl())){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
}
if(StringUtils.isEmpty(permissionReqVo.getMethod())){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_METHOD_NULL);
}
if(StringUtils.isEmpty(permissionReqVo.getCode())){
throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_CODE_NULL);
}
}
}else{
throw new BusinessException(ResponseCode.DATA_ERROR);
}
}
/**
* 删除菜单权限
* @param permissionId
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Response<String> deletedPermission(String permissionId) {
//判断是否有子集关联有则不能删除
int resultCount = sysPermissionDao.selectChild(permissionId);
if (resultCount > 0){
throw new BusinessException(ResponseCode.ROLE_PERMISSION_RELATION);
}
//通过权限id删除相关角色和该菜单权限的关联表信息
rolePermissionService.removeRoleByPermissionId(permissionId);
// 删除权限菜单表
SysPermission sysPermission = new SysPermission();
sysPermission.setId(permissionId);
sysPermission.setDeleted(0);
sysPermission.setUpdateTime(new Date());
int updateCount = sysPermissionDao.updateByPrimaryKeySelective(sysPermission);
if (updateCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
// 标记用户主动去刷新
// 通过权限 id 查询所有的角色 id
List<String> roleIdsByPermissionId = rolePermissionService.getRoleIdsByPermissionId(permissionId);
if (roleIdsByPermissionId != null && !roleIdsByPermissionId.isEmpty()){
// 通过角色 id 查询所有的用户 id
List<String> userIdsByRoleIds = userRoleService.getUserIdsByRoleIds(roleIdsByPermissionId);
if (userIdsByRoleIds!=null && !userIdsByRoleIds.isEmpty()){
for (String userId :userIdsByRoleIds){
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+userId,userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
}
}
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 获取所有权限包括按钮角色添加/编辑/分配权限时用到的结结构数据
* @return
*/
@Override
public List<PermissionRespNodeVo> selectAllTree() {
return getTree(selectAll(),true);
}
}

View File

@ -0,0 +1,93 @@
package com.suelec.permission.service.impl;
import com.suelec.permission.dao.SysRolePermissionDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysRolePermission;
import com.suelec.permission.service.RolePermissionService;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.vo.req.RolePermissionOperationReqVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class RolePermissionServiceImpl implements RolePermissionService {
@Autowired
private SysRolePermissionDao sysRolePermissionDao;
@Autowired
private IdWorker idWorker;
/**
* 插入角色权限关联表数据
* @param operationReqVo
*/
@Override
public void addRolePermission(RolePermissionOperationReqVo operationReqVo) {
if (null == operationReqVo.getPermissionIds()){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
// 添加之前先删除原来角色 id 对应的所有权限id
sysRolePermissionDao.removeByRoleId(operationReqVo.getRoleId());
// 权限id集合为空表示删除该角色对应的所有权限
if (operationReqVo.getPermissionIds().isEmpty()){
return;
}
Date date = new Date();
List<SysRolePermission> list = new ArrayList<>();
for (String permissionId : operationReqVo.getPermissionIds()){
SysRolePermission sysRolePermission = new SysRolePermission();
sysRolePermission.setId(String.valueOf(idWorker.nextId()));
sysRolePermission.setRoleId(operationReqVo.getRoleId());
sysRolePermission.setPermissionId(permissionId);
sysRolePermission.setCreateTime(date);
list.add(sysRolePermission);
}
int result = sysRolePermissionDao.batchRolePermission(list);
if (result == 0){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
}
/**
* 通过权限 id 查询所有的角色 id
* @param permissionId
* @return
*/
@Override
public List<String> getRoleIdsByPermissionId(String permissionId) {
return sysRolePermissionDao.getRoleIdsByPermissionId(permissionId);
}
/**
* 通过权限id删除相关角色和该菜单权限的关联表信息
* @param permissionId
*/
@Override
public int removeRoleByPermissionId(String permissionId) {
return sysRolePermissionDao.removeByPermissionId(permissionId);
}
/**
* 通过角色id查询拥有的权限id
* @param roleId
*/
@Override
public List<String> getPermissionIdsByRoleId(String roleId) {
return sysRolePermissionDao.getPermissionIdsByRoleId(roleId);
}
/**
* 通过角色id删除权限id
* @param roleId
* @return
*/
@Override
public int removeByRoleId(String roleId) {
return sysRolePermissionDao.removeByRoleId(roleId);
}
}

View File

@ -0,0 +1,232 @@
package com.suelec.permission.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.suelec.permission.config.TokenConfig;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.dao.SysRoleDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysRole;
import com.suelec.permission.service.PermissionService;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.service.RolePermissionService;
import com.suelec.permission.service.RoleService;
import com.suelec.permission.service.UserRoleService;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.utils.PageUtil;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.RolePageReqVo;
import com.suelec.permission.vo.req.RolePermissionOperationReqVo;
import com.suelec.permission.vo.req.RoleReqVo;
import com.suelec.permission.vo.req.RoleUpdateReqVo;
import com.suelec.permission.vo.resp.PageVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class RoleServiceImpl implements RoleService {
private static Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);
@Autowired
private SysRoleDao sysRoleDao;
@Autowired
private RolePermissionService rolePermissionService;
@Autowired
private IdWorker idWorker;
@Autowired
private PermissionService permissionService;
@Autowired
private RedisService redisService;
@Autowired
private UserRoleService userRoleService;
@Autowired
private TokenConfig tokenConfig;
/**
* 角色管理分页数据
* @param rolePageReqVo
* @return
*/
@Override
public Response<PageVo> pageInfoRoles(RolePageReqVo rolePageReqVo) {
PageHelper.startPage(rolePageReqVo.getPageNum(),rolePageReqVo.getPageSize());
List<SysRole> sysRoles = sysRoleDao.selectAll(rolePageReqVo);
return Response.success(PageUtil.getPageVo(new PageInfo<SysRole>(sysRoles)));
}
/**
* 新增角色
* @param roleReqVo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Response<String> createRole(RoleReqVo roleReqVo) {
if (null == roleReqVo.getPermissionsIds() || roleReqVo.getPermissionsIds().isEmpty()){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
String roleId = String.valueOf(idWorker.nextId());
// 角色入库
SysRole sysRole = SysRole.builder()
.id(roleId)
.name(roleReqVo.getName())
.status(roleReqVo.getStatus())
.description(roleReqVo.getDescription())
.createTime(new Date())
.build();
int addCount = sysRoleDao.insertSelective(sysRole);
if (addCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
// 添加 角色 权限关联表 数据
RolePermissionOperationReqVo rolePermissionOperationReqVo = new RolePermissionOperationReqVo();
rolePermissionOperationReqVo.setRoleId(roleId);
rolePermissionOperationReqVo.setPermissionIds(roleReqVo.getPermissionsIds());
rolePermissionService.addRolePermission(rolePermissionOperationReqVo);
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 查询所有权限
* @return
*/
@Override
public List<SysRole> selectAll() {
return sysRoleDao.selectAll(new RolePageReqVo());
}
/**
* 获取角色详情数据
* @param roleId
* @return
*/
@Override
public Response<Set<String>> detailInfo(String roleId) {
if (StringUtils.isBlank(roleId)){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
SysRole sysRole = sysRoleDao.selectByPrimaryKey(roleId);
if (sysRole == null){
logger.info("传入 的 id:{}不合法",roleId);
throw new BusinessException(ResponseCode.DATA_ERROR);
}
// 通过角色id查询拥有的权限ids
List<String> permissionIdsByRoleId = rolePermissionService.getPermissionIdsByRoleId(roleId);
Set<String> permissionIds = new HashSet<>(permissionIdsByRoleId);
return Response.success(permissionIds);
}
/**
* 更新角色信息
* @param roleUpdateReqVo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Response<String> updateRole(RoleUpdateReqVo roleUpdateReqVo) {
SysRole sysRole = sysRoleDao.selectByPrimaryKey(roleUpdateReqVo.getId());
if (sysRole == null){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
BeanUtils.copyProperties(roleUpdateReqVo,sysRole);
sysRole.setUpdateTime(new Date());
int updateCount = sysRoleDao.updateByPrimaryKeySelective(sysRole);
if (updateCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
// 更新 角色 权限 关联表
RolePermissionOperationReqVo rolePermissionOperationReqVo = new RolePermissionOperationReqVo();
rolePermissionOperationReqVo.setRoleId(roleUpdateReqVo.getId());
rolePermissionOperationReqVo.setPermissionIds(roleUpdateReqVo.getPermissionsIds());
rolePermissionService.addRolePermission(rolePermissionOperationReqVo);
// 标记关联用户主动去刷新
// 通过 角色id 查询所有的用户ids
List<String> userIdsByRoleId = userRoleService.getUserIdsByRoleId(roleUpdateReqVo.getId());
if (null != userIdsByRoleId && !userIdsByRoleId.isEmpty()){
for (String userId : userIdsByRoleId){
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+userId,userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
}
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 更新角色状态
* @param roleId
* @param status
* @return
*/
@Override
public Response<String> updateRoleStatus(String roleId, Integer status) {
if (StringUtils.isBlank(roleId)|| ObjectUtils.isEmpty(status)){
return Response.error(ResponseCode.DATA_ERROR.getMessage());
}
SysRole sysRole = new SysRole();
sysRole.setId(roleId);
sysRole.setStatus(status);
int result = sysRoleDao.updateByPrimaryKeySelective(sysRole);
if (result == 0){
return Response.error(ResponseCode.OPERATION_ERROR.getMessage());
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 删除角色信息
* @param roleId
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Response<String> deletedRole(String roleId) {
// 1.
SysRole sysRole = new SysRole();
sysRole.setId(roleId);
sysRole.setDeleted(0);
sysRole.setUpdateTime(new Date());
int updateCount = sysRoleDao.updateByPrimaryKeySelective(sysRole);
if (updateCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
// 2.角色菜单权限关联数据删除通过角色id删除权限id
rolePermissionService.removeByRoleId(roleId);
// 3.查询需要标记主动刷新的用户
List<String> userIdsByRoleId = userRoleService.getUserIdsByRoleId(roleId);
// 4.用户角色关联信息删除通过角色id删除用户id
userRoleService.removeUseIdsrRoleId(roleId);
// 5.把跟该角色关联的用户标记起来需要主动刷新token
if (userIdsByRoleId != null && !userIdsByRoleId.isEmpty()){
for (String userId : userIdsByRoleId){
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+userId,userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
}
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
}

View File

@ -0,0 +1,96 @@
package com.suelec.permission.service.impl;
import com.suelec.permission.dao.SysUserRoleDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysUserRole;
import com.suelec.permission.service.UserRoleService;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.vo.req.UserOwnRoleReqVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class UserRoleServiceImpl implements UserRoleService {
@Autowired
private SysUserRoleDao sysUserRoleDao;
@Autowired
private IdWorker idWorker;
/**
* 根据用户id 查询用户拥有的角色数据接口
* @param userId
*/
@Override
public List<String> getRoleIdsByUserId(String userId) {
return sysUserRoleDao.getRoleIdsByUserId(userId);
}
/**
* 更新用户角色
* @param userOwnRoleReqVo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void addUserRoleInfo(UserOwnRoleReqVo userOwnRoleReqVo) {
if (userOwnRoleReqVo.getUserId() == null){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
// 先删除用户原来的拥有的角色id
sysUserRoleDao.removeRoleIdsByUserId(userOwnRoleReqVo.getUserId());
if (userOwnRoleReqVo.getRoleIds().isEmpty()){// 为空表示去除该用户所有角色
return;
}
// 批量插入用户角色数据
List<SysUserRole> list = new ArrayList<>();
for (String roleId : userOwnRoleReqVo.getRoleIds()){
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setId(String.valueOf(idWorker.nextId()));
sysUserRole.setUserId(userOwnRoleReqVo.getUserId());
sysUserRole.setRoleId(roleId);
sysUserRole.setCreateTime(new Date());
list.add(sysUserRole);
}
int result = sysUserRoleDao.batchInsertUserRole(list);
if (result == 0){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
}
/**
* 通过角色 id 集合查询所有的用户 id
* @param roleIdsByPermissionId
* @return
*/
@Override
public List<String> getUserIdsByRoleIds(List<String> roleIdsByPermissionId) {
return sysUserRoleDao.getUserIdsByRoleIds(roleIdsByPermissionId);
}
/**
* 通过 单个角色id 查询所有的用户ids
* @param roleId
* @return
*/
@Override
public List<String> getUserIdsByRoleId(String roleId) {
return sysUserRoleDao.getUserIdsByRoleId(roleId);
}
/**
* 通过角色id删除用户id
* @param roleId
* @return
*/
@Override
public int removeUseIdsrRoleId(String roleId) {
return sysUserRoleDao.removeUseIdsrRoleId(roleId);
}
}

View File

@ -0,0 +1,419 @@
package com.suelec.permission.service.impl;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.suelec.permission.config.TokenConfig;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.dao.SysUserDao;
import com.suelec.permission.dao.SysUserRoleDao;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.pojo.SysUser;
import com.suelec.permission.pojo.Tuser;
import com.suelec.permission.service.PermissionService;
import com.suelec.permission.service.RoleService;
import com.suelec.permission.service.UserRoleService;
import com.suelec.permission.service.UserService;
import com.suelec.permission.utils.IdWorker;
import com.suelec.permission.utils.JwtTokenUtil;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.utils.PageUtil;
import com.suelec.permission.utils.Response;
import com.suelec.permission.vo.req.LoginReqVo;
import com.suelec.permission.vo.req.UserAddReqVo;
import com.suelec.permission.vo.req.UserOwnRoleReqVo;
import com.suelec.permission.vo.req.UserPageReqVo;
import com.suelec.permission.vo.req.UserUpdateDetailInfoReqVo;
import com.suelec.permission.vo.req.UserUpdatePasswordReqVo;
import com.suelec.permission.vo.req.UserUpdateReqVo;
import com.suelec.permission.vo.resp.LoginRespVo;
import com.suelec.permission.vo.resp.PageVo;
import com.suelec.permission.vo.resp.PermissionRespNodeVo;
import com.suelec.permission.vo.resp.UserOwnRoleRespVo;
import com.suelec.permission.vo.resp.UserRespVo;
import com.suelec.permission.vo.resp.UserTableRespVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private TokenConfig tokenConfig;
@Autowired
private RedisService redisService;
@Autowired(required = false)
private SysUserDao sysUserDao;
@Autowired
private IdWorker idWorker;
@Autowired
private UserRoleService userRoleService;
@Autowired
private RoleService roleService;
@Autowired
private PermissionService permissionService;
@Autowired(required = false)
private SysUserRoleDao sysUserRoleDao;
/**
* 登陆
* @param loginReqVo
* @return
*/
@Override
public Response<LoginRespVo> login(LoginReqVo loginReqVo) {
Tuser user = sysUserDao.findByUsername(loginReqVo.getUsername());
if (null == user){// 账号不存在
throw new BusinessException(ResponseCode.ACCOUNT_ERROR);
}
// if (!BCrypt.checkpw(loginReqVo.getPassword(),user.getPassword())){// 密码不正确
// throw new BusinessException(ResponseCode.ACCOUNT_PASSWORD_ERROR);
// }
if (user.getStatus() == 2){// 账号锁定
return Response.error(ResponseCode.ACCOUNT_LOCK.getMessage());
}
// 查询用户拥有的权限菜单列表
List<PermissionRespNodeVo> permissionRespNodeVos = permissionService.permissionTreeListByUserId(user.getId()+"");
// 查询前端按钮权限
List<String> permissionCodes = sysUserRoleDao.getPermissionCodesByUserId(user.getId()+"");
// 通过用户id获取该用户所拥有的角色名称
List<String> roleNames = sysUserRoleDao.getRoleNameByUserId(user.getId()+"");
// 通过用户id获取该用户所拥有的权限授权 sys:user:add
List<String> permissionPerms = sysUserRoleDao.getPermissionPermsByUserId(user.getId()+"");
/*List<String> roleNames = new ArrayList<>();
roleNames.add("admin");
List<String> permissionPerms = new ArrayList<>();
permissionPerms.add("sys:user");
permissionPerms.add("user:test");*/
// 用户业务 token 令牌
String accessToken = JwtTokenUtil.getInstance()
.setIssuer(tokenConfig.getIssuer())
.setSecret(tokenConfig.getSecretKey())
.setExpired(tokenConfig.getAccessTokenExpireTime().toMillis())
.setSubObject(user.getId()+"")
.setClaim(Constant.JWT_ROLES_KEY, JSON.toJSONString(roleNames))
.setClaim(Constant.JWT_PERMISSIONS_KEY, JSON.toJSONString(permissionPerms))
.setClaim(Constant.JWT_USER_NAME, user.getName())
.generateToken();
// 每次登录的时候吧token放到 redis用于只能一个账号同时在线
redisService.set(Constant.JWT_USER_NAME+user.getId(),accessToken);
// 每次登录先删除需要重新登录的标记
redisService.delete(Constant.JWT_USER_LOGIN_BLACKLIST+user.getId());
LoginRespVo loginRespVo = new LoginRespVo();
loginRespVo.setAuthorization(accessToken);
loginRespVo.setId(user.getId()+"");
loginRespVo.setPhone(user.getPhone());
loginRespVo.setUsername(user.getName());
loginRespVo.setNickname(user.getName());
loginRespVo.setMenus(permissionRespNodeVos);
loginRespVo.setPermissions(permissionCodes);
return Response.success(loginRespVo);
}
/**
* 退出登陆
* @param accessToken
* @return
*/
@Override
public Response<String> logout(String accessToken) {
if (StringUtils.isBlank(accessToken)){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
// shiro 退出
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated()){
subject.logout();
}
// 获取用户 id
String userId = JwtTokenUtil.getInstance().getUserId(accessToken);
// 每次退出登录先删除需要重新登录的标记
redisService.delete(Constant.JWT_USER_LOGIN_BLACKLIST+userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
return Response.success();
}
/**
* 分页查询用户包括搜索条件
* @param userPageReqVo
* @return
*/
@Override
public Response<PageVo<UserTableRespVo>> pageInfo(UserPageReqVo userPageReqVo) {
PageHelper.startPage(userPageReqVo.getPageNum(),userPageReqVo.getPageSize());
List<UserTableRespVo> sysUsers = sysUserDao.selectAll(userPageReqVo);
return Response.success(PageUtil.getPageVo(new PageInfo<UserTableRespVo>(sysUsers)));
}
/**
* 新增用户
* @param userAddReqVo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Response<String> addUser(UserAddReqVo userAddReqVo) {
if (sysUserDao.findByUsername(userAddReqVo.getUsername()) != null){
throw new BusinessException(ResponseCode.ACCOUNT_EXISTS_ERROR);
}
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(userAddReqVo,sysUser);
String salt = BCrypt.gensalt();
sysUser.setId(String.valueOf(idWorker.nextId()));
sysUser.setPassword(BCrypt.hashpw(userAddReqVo.getPassword(),salt));
sysUser.setCreateTime(new Date());
if (sysUserDao.insertSelective(sysUser) != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 查询用户拥有的角色数据接口
* @param userId
* @return
*/
@Override
public Response<UserOwnRoleRespVo> getUserOwnRole(String userId) {
UserOwnRoleRespVo userOwnRoleRespVo = new UserOwnRoleRespVo();
userOwnRoleRespVo.setOwnRoleIds(userRoleService.getRoleIdsByUserId(userId));
userOwnRoleRespVo.setAllRole(roleService.selectAll());
return Response.success(userOwnRoleRespVo);
}
/**
* 更新用户角色
* @param vo
* @return
*/
@Override
public Response<String> setUserOwnRole(UserOwnRoleReqVo vo) {
// 更新用户角色关联表信息
userRoleService.addUserRoleInfo(vo);
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+vo.getUserId(),vo.getUserId());
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+vo.getUserId());
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 刷新token接口 重新签发 token
* @param refreshToken
* @return
*/
/*public Response refreshToken(String refreshToken){
// 判断 token是否过期 或是否加入黑名单
JwtTokenUtil instance = JwtTokenUtil.getInstance();
if (!instance.checkToken(refreshToken) || redisService.hasKey(Constant.JWT_REFRESH_TOKEN_BLACKLIST+refreshToken)){
throw new BusinessException(ResponseCode.TOKEN_ERROR);
}
// 主动刷新比如修改用户角色后需要重新登陆
// 重新签发 token 标记刷新 token
String userId = instance.getUserId(refreshToken);
List<String> roleIds = new ArrayList<>();
Set<String> permissions = new HashSet<>();
if (redisService.hasKey(Constant.JWT_REFRESH_KEY + userId)){
// 存在表示需要主动刷新
roleIds = userRoleService.getRoleIdsByUserId(userId);
permissions = getPermissionsByUserId(userId);
}
String newAccessToken = instance.setClaim(Constant.JWT_ROLES_KEY, JSON.toJSONString(roleIds))
.setClaim(Constant.JWT_PERMISSIONS_KEY, JSON.toJSONString(permissions))
.setExpired(tokenConfig.getAccessTokenExpireTime().toMillis())
.generateToken();
*//*if(redisService.hasKey(Constant.JWT_REFRESH_KEY+userId)){
redisService.set(Constant.JWT_REFRESH_IDENTIFICATION+newAccessToken,userId, redisService.getExpire(Constant.JWT_REFRESH_KEY+userId,TimeUnit.MILLISECONDS),TimeUnit.MILLISECONDS);
}*//*
Map map = new HashMap<>();
//map.put("authorization",newAccessToken);
map.put("authorization",newAccessToken);
return Response.success(map);
}*/
/**
* 通过用户id获取该用户所拥有的角色
* @param userId
*/
/*public Set<String> getPermissionsByUserId(String userId){
return permissionService.getPermissionByUserId(userId);
}*/
/**
* 更新用户信息
* @param userUpdateReqVo
* @param operationId 操作人
* @return
*/
@Override
public Response<String> updateUserInfo(UserUpdateReqVo userUpdateReqVo, String operationId) {
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(userUpdateReqVo,sysUser);
sysUser.setUpdateId(operationId);
sysUser.setUpdateTime(new Date());
if (StringUtils.isBlank(userUpdateReqVo.getPassword())){
sysUser.setPassword(StringUtils.EMPTY);
}else{
sysUser.setPassword(BCrypt.hashpw(userUpdateReqVo.getPassword(),BCrypt.gensalt()));
}
int result = sysUserDao.updateSelective(sysUser);
if (result == 0){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
if(userUpdateReqVo.getStatus() == 2){
// 账号锁定需要更新 redis 账号锁定状态
redisService.set(Constant.ACCOUNT_LOCK_KEY+sysUser.getId(),sysUser.getId());
}else {
// 删除账号锁定状态
redisService.delete(Constant.ACCOUNT_LOCK_KEY+sysUser.getId());
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 批量/删除用户接口
* @param list
* @param operationId 操作人
* @return
*/
@Override
public Response<String> deletedUsers(List<String> list, String operationId) {
// 更新操作人
SysUser sysUser = new SysUser();
sysUser.setUpdateId(operationId);
sysUser.setUpdateTime(new Date());
int result = sysUserDao.deletedUsers(sysUser,list);
if (result == 0){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
for (String userId : list){
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.delete(Constant.JWT_USER_LOGIN_BLACKLIST + userId);
/**
* 更新 redis 账号的删除状态
*/
redisService.set(Constant.DELETED_USER_KEY + userId,userId,tokenConfig.getAccessTokenExpireTime().toMillis(),TimeUnit.MILLISECONDS);
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 获取个人资料编辑信息
* @param userId
* @return
*/
@Override
public Response<UserRespVo> detailInfo(String userId) {
if (StringUtils.isBlank(userId)){
return Response.error(ResponseCode.DATA_ERROR.getMessage());
}
SysUser sysUser = sysUserDao.selectByPrimaryKey(userId);
UserRespVo userRespVo = new UserRespVo();
BeanUtils.copyProperties(sysUser,userRespVo);
return Response.success(userRespVo);
}
/**
* 保存个人信息接口
* @param updateDetailInfoReqVo
* @param userId
* @return
*/
@Override
public Response<String> userUpdateDetailInfo(UserUpdateDetailInfoReqVo updateDetailInfoReqVo, String userId) {
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(updateDetailInfoReqVo,sysUser);
sysUser.setId(userId);
sysUser.setUpdateId(userId);
sysUser.setUpdateTime(new Date());
int updateCount = sysUserDao.updateSelective(sysUser);
if (updateCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 重置用户密码
* @param userId
* @return
*/
@Override
public Response<String> resetUpdatePassword(String userId) {
SysUser sysUser = sysUserDao.selectByPrimaryKey(userId);
if (sysUser == null){
return Response.error(ResponseCode.ACCOUNT_ERROR.getMessage());
}
SysUser user = new SysUser();
user.setId(userId);
user.setPassword(BCrypt.hashpw("123456",BCrypt.gensalt()));
int result = sysUserDao.updateSelective(user);
if (result == 0){
return Response.error(ResponseCode.OPERATION_ERROR.getMessage());
}
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST + userId,userId);
return Response.success(ResponseCode.SUCCESS.getMessage());
}
/**
* 修改个人密码
* @param userUpdatePasswordReqVo
* @param accessToken
* @return
*/
@Override
public Response<String> userUpdatePassword(UserUpdatePasswordReqVo userUpdatePasswordReqVo, String accessToken) {
JwtTokenUtil instance = JwtTokenUtil.getInstance();
String userId = instance.getUserId(accessToken);
if (StringUtils.isBlank(userId)){
throw new BusinessException(ResponseCode.DATA_ERROR);
}
SysUser sysUser = sysUserDao.selectByPrimaryKey(userId);
if (sysUser == null){
throw new BusinessException(ResponseCode.TOKEN_ERROR);
}
if (!BCrypt.checkpw(userUpdatePasswordReqVo.getOldPwd(),sysUser.getPassword())){
throw new BusinessException(ResponseCode.OLD_PASSWORD_ERROR);
}
sysUser.setUpdateId(userId);
sysUser.setPassword(BCrypt.hashpw(userUpdatePasswordReqVo.getNewPwd(),BCrypt.gensalt()));
sysUser.setUpdateTime(new Date());
int updateCount = sysUserDao.updateSelective(sysUser);
if (updateCount != 1){
throw new BusinessException(ResponseCode.OPERATION_ERROR);
}
/**
* 标记用户需要重新登录,禁止再访问我们的系统资源
*/
redisService.set(Constant.JWT_USER_LOGIN_BLACKLIST+userId,userId);
/**
* 清楚用户授权数据缓存
*/
redisService.delete(Constant.IDENTIFY_CACHE_KEY+userId);
return Response.success(ResponseCode.SUCCESS.getMessage());
}
}

View File

@ -0,0 +1,124 @@
package com.suelec.permission.shiro;
import com.alibaba.fastjson.JSON;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.AccessControlFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 效验请求是否携带 token ,此时还未进入 controller 所以抛出的异常捕获不到只能直接输出 json
*/
@Slf4j
public class CustomAccessControllerFilter extends AccessControlFilter {
/** springbootshiro跨域CORS请求拿不到headers中的token值解决
* 处理前后端分离时获取不到token
* @param request
* @param response
* @return
* @throws Exception
*/
/*@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())){
httpResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"));
httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
httpResponse.setHeader("Content-Type","application/json;charset=UTF-8");
httpResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(httpRequest, httpResponse);
}*/
/** 判断用户是否已经登录
* 返回 true 则进入过滤器链中的下一个过滤器
* 返回 false 则进入 onAccessDenied 方法进行效验
* @param servletRequest
* @param servletResponse
* @param o
* @return
* @throws Exception
*/
@Override
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
return false;
}
/**
* 效验是否携带 token 此时还未进入 controller 所以抛出的异常捕获不到只能直接输出 json
* @param servletRequest
* @param servletResponse
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
try {
String accessToken = request.getHeader(Constant.ACCESS_TOKEN);
if (StringUtils.isBlank(accessToken)) {
throw new BusinessException(ResponseCode.TOKEN_NOT_NULL);
}
// accessToken 设置进 Shiro
CustomUsernamePasswordToken customUsernamePasswordToken = new CustomUsernamePasswordToken(accessToken);
/************************* Shiro 认证 *************************
Subject主体即用户
在Shiro中subject是一个接口,面向程序员的接口程序员使用Subject接口执行认证操作
调用subject.login(token)执行认证
*/
getSubject(servletRequest, servletResponse).login(customUsernamePasswordToken);
}catch (BusinessException e){
responseJson(response,e.getCode(),e.getMessage());
return false;
}catch (AuthenticationException e){// 认证异常
log.info("【打印 e.getCause 】,{}",e.getCause());
// 判断该异常是我们手动抛出还是 Shiro 抛出为了区分提示信息
if (e.getCause() instanceof BusinessException){ // 手动抛出
BusinessException exception = (BusinessException) e.getCause();
responseJson(response,exception.getCode(),exception.getMessage());
}else if (e.getCause() instanceof ShiroException){ // Shiro 抛出
// 用户认证异常登陆
responseJson(response,ResponseCode.SHIRO_AUTHENTICATION_ERROR.getCode(),ResponseCode.SHIRO_AUTHENTICATION_ERROR.getMessage());
}else { // 系统异常
responseJson(response,ResponseCode.SYSTEM_ERROR.getCode(),ResponseCode.SYSTEM_ERROR.getMessage());
}
return false;
}
return true;
}
/**
* 返回 json
* @param response
* @param message
*/
private void responseJson(HttpServletResponse response,int code,String message){
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("UTF-8");
try {
PrintWriter writer = response.getWriter();
writer.write(JSON.toJSONString(Response.error(code,message)));
writer.close();
response.flushBuffer();
} catch (IOException e) {
log.error("【输出 JSON 异常】,{}",e);
}
}
}

View File

@ -0,0 +1,68 @@
package com.suelec.permission.shiro;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.enums.ResponseCode;
import com.suelec.permission.exception.BusinessException;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.utils.JwtTokenUtil;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;
/** 自定义的认证器
*
* Shiro 认证器 HashedCredentialsMatcher
* Shiro主要是用过 HashedCredentialsMatcher doCredentialsMatch方法对提交的用户名密码组装的 token 进行效验我们这使用的是 jwt-token
*/
public class CustomHashedCredentialsMatcher extends HashedCredentialsMatcher {
@Autowired
private RedisService redisService;
/**
* 真正的效验主要是通过 HashedCredentialsMatcher doCredentialsMatch 方法返回值进行效验
* 我们使用的是 jwt-token 所以在此处效验
* @param token
* @param info
* @return
*/
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
CustomUsernamePasswordToken customUsernamePasswordToken = (CustomUsernamePasswordToken) token;
String accessToken = (String) customUsernamePasswordToken.getPrincipal();
String userId = JwtTokenUtil.getInstance().getUserId(accessToken);
/**
* 判断用户是否被锁定
*/
if (redisService.hasKey(Constant.ACCOUNT_LOCK_KEY + userId)){
throw new BusinessException(ResponseCode.ACCOUNT_LOCK);
}
/**
* 判断用户是否被删除
*/
if (redisService.hasKey(Constant.DELETED_USER_KEY + userId)){
throw new BusinessException(ResponseCode.ACCOUNT_HAS_DELETED_ERROR);
}
/**
* 判断用户是否在加入黑名单 禁止再访问我们的系统资源让用户重新登录
*/
// if (redisService.hasKey(Constant.JWT_USER_LOGIN_BLACKLIST + userId)){
// throw new BusinessException(ResponseCode.TOKEN_PAST_DUE);
// }
/**
* 判断token是否通过校验不通过token 失效
*/
// if (!JwtTokenUtil.getInstance().checkToken(accessToken)){
// throw new BusinessException(ResponseCode.TOKEN_PAST_DUE);
// }
// if (redisService.hasKey(Constant.JWT_USER_NAME+userId)){
// String userAccessToken = (String) redisService.get(Constant.JWT_USER_NAME+userId);
// if (!accessToken.equals(userAccessToken)){
// throw new BusinessException(ResponseCode.TOKEN_EXISTS);
// }
// }
return true;
}
}

View File

@ -0,0 +1,82 @@
package com.suelec.permission.shiro;
import com.suelec.permission.dao.SysUserRoleDao;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.utils.JwtTokenUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/** 自定义域 CustomRealm
*
* Realm即领域相当于datasource数据源securityManager进行安全认证需要通过Realm获取用户身份信息及用户权限数据
* 比如如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息
*/
public class CustomRealm extends AuthorizingRealm {
@Autowired
private RedisService redisService;
@Autowired
private SysUserRoleDao sysUserRoleDao;
/**
* 此方法必须有不然我们自定义的 CustomUsernamePasswordToken 不生效
* @param token
* @return
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof CustomUsernamePasswordToken;
}
/**
* 用户授权设置用户所拥有的 角色/权限
* @param principals
* @return
* @throws AuthenticationException
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String accessToken = (String) principals.getPrimaryPrincipal();
// 授权器
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
JwtTokenUtil instance = JwtTokenUtil.getInstance();
String userId = instance.getUserId(accessToken);
// 判断 redis 中是否缓存有权限信息
//if (redisService.hasKey(Constant.IDENTIFY_CACHE_KEY + userId)){
// redisService.get(Constant.IDENTIFY_CACHE_KEY + userId);
//}
// 通过用户id获取该用户所拥有的角色名称
List<String> roleNames = sysUserRoleDao.getRoleNameByUserId(userId);
if (roleNames != null && !roleNames.isEmpty()){
authorizationInfo.addRoles(roleNames);
}
// 通过用户id获取该用户所拥有的权限授权 sys:user:add
List<String> permissionPerms = sysUserRoleDao.getPermissionPermsByUserId(userId);
if (permissionPerms != null && !permissionPerms.isEmpty()){
authorizationInfo.addStringPermissions(permissionPerms);
}
return authorizationInfo;
}
/**
* 用户认证以前是验证用户名/密码现在我们验证 token吧我们的 token 交还给 认证器
* @param token
* @return
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 把我们的 token 交还给 认证器
CustomUsernamePasswordToken customUsernamePasswordToken = (CustomUsernamePasswordToken) token;
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(customUsernamePasswordToken.getPrincipal(), customUsernamePasswordToken.getCredentials(), CustomRealm.class.getName());
return info;
}
}

View File

@ -0,0 +1,20 @@
package com.suelec.permission.shiro;
import org.apache.shiro.authc.UsernamePasswordToken;
/**
* Shiro 不支持 jwt-token所以我们需要继承 UsernamePasswordToken jwt-token 设置到 Shiro
*/
public class CustomUsernamePasswordToken extends UsernamePasswordToken {
private String token;
public CustomUsernamePasswordToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
}

View File

@ -0,0 +1,202 @@
package com.suelec.permission.shiro;
import com.alibaba.fastjson.JSON;
import com.suelec.permission.constarts.Constant;
import com.suelec.permission.service.RedisService;
import com.suelec.permission.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 自定义 角色 权限 缓存 继承 Shiro Cache 接口
*/
@Slf4j
public class RedisCache<K,V> implements Cache<K,V> {
private String cacheKey;// key
private long expire = 24; // 缓存一天过期时间
private RedisService redisService;
public RedisCache(RedisService redisService){
this.cacheKey = Constant.IDENTIFY_CACHE_KEY;
this.redisService = redisService;
}
// 解析 token缓存 key
private String getRedisCacheKey(K key){
if(null==key){
return null;
}else {
return this.cacheKey + JwtTokenUtil.getInstance().getUserId(key.toString());
}
}
/**
* 获取缓存
* @param key
* @return
* @throws CacheException
*/
@Override
public V get(K key) throws CacheException {
log.info("Shiro从缓存中获取数据KEY值[{}]",key);
if (key == null) {
return null;
}
try{
String redisCacheKey = getRedisCacheKey(key);
Object rawValue = redisService.get(redisCacheKey);
if (rawValue == null){
return null;
}
SimpleAuthorizationInfo simpleAuthorizationInfo = JSON.parseObject(rawValue.toString(),SimpleAuthorizationInfo.class);
V value = (V) simpleAuthorizationInfo;
return value;
}catch (Exception e){
throw new CacheException(e);
}
}
/**
* 设置缓存
* @param key
* @param value
* @return
* @throws CacheException
*/
@Override
public V put(K key, V value) throws CacheException {
log.info("put key [{}]",key);
if (key == null) {
log.warn("Saving a null key is meaningless, return value directly without call Redis.");
return value;
}
try {
String redisCacheKey = getRedisCacheKey(key);
redisService.set(redisCacheKey,value == null ? null : value,expire, TimeUnit.HOURS);
return value;
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* 删除 key
* @param key
* @return
* @throws CacheException
*/
@Override
public V remove(K key) throws CacheException {
log.info("remove key [{}]",key);
if (key == null){
return null;
}
try {
String redisCacheKey = getRedisCacheKey(key);
Object rawValue = redisService.get(redisCacheKey);
V previous = (V) rawValue;
redisService.delete(redisCacheKey);
return previous;
} catch (Exception e) {
throw new CacheException(e);
}
}
/**
* 清空
* @throws CacheException
*/
@Override
public void clear() throws CacheException {
log.debug("clear cache");
Set<String> keys = null;
try {
keys = redisService.keys(this.cacheKey + "*");
} catch (Exception e) {
log.error("get keys error", e);
}
if (keys == null || keys.size() == 0) {
return;
}
for (String key: keys) {
redisService.delete(key);
}
}
/**
* 获取 key 长度
* @return
*/
@Override
public int size() {
int result = 0;
try {
result = redisService.keys(this.cacheKey + "*").size();
} catch (Exception e) {
log.error("get keys error", e);
}
return result;
}
@Override
public Set keys() {
Set<String> keys = null;
try {
keys = redisService.keys(this.cacheKey + "*");
} catch (Exception e) {
log.error("get keys error", e);
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}
Set<K> convertedKeys = new HashSet<>();
for (String key:keys) {
try {
convertedKeys.add((K) key);
} catch (Exception e) {
log.error("deserialize keys error", e);
}
}
return convertedKeys;
}
@Override
public Collection values() {
Set<String> keys = null;
try {
keys = redisService.keys(this.cacheKey + "*");
} catch (Exception e) {
log.error("get values error", e);
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}
List<V> values = new ArrayList<V>(keys.size());
for (String key : keys) {
V value = null;
try {
value = (V) redisService.get(key);
} catch (Exception e) {
log.error("deserialize values= error", e);
}
if (value != null) {
values.add(value);
}
}
return Collections.unmodifiableList(values);
}
}

View File

@ -0,0 +1,22 @@
package com.suelec.permission.shiro;
import com.suelec.permission.service.RedisService;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 缓存管理器
*/
public class RedisCacheManager implements CacheManager {
// 注入 redis
@Autowired
private RedisService redisService;
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
return new RedisCache<>(redisService);
}
}

View File

@ -0,0 +1,142 @@
package com.suelec.permission.shiro;
//import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
/** 分离模式不需要
* thymeleaf-shiro 权限标签配置
* @return
*/
/*@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}*/
/**
* 缓存管理器
* @return
*/
@Bean
public RedisCacheManager redisCacheManager(){
return new RedisCacheManager();
}
/**
* 注入自定义认证器
* @return
*/
@Bean
public CustomHashedCredentialsMatcher customHashedCredentialsMatcher(){
return new CustomHashedCredentialsMatcher();
}
/**
* 注入自定义域
* @return
*/
@Bean
public CustomRealm customRealm(){
CustomRealm customRealm = new CustomRealm();
// 注入认证器 CustomHashedCredentialsMatcher
customRealm.setCredentialsMatcher(customHashedCredentialsMatcher());
// 设置缓存管理器
customRealm.setCacheManager(redisCacheManager());
return customRealm;
}
/**
* 安全管理器
* @return
*/
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
// 注入域 Realm
defaultWebSecurityManager.setRealm(customRealm());
return defaultWebSecurityManager;
}
/**
* shiro过滤器配置拦截哪些请求
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 注入管理器
shiroFilterFactoryBean.setSecurityManager(securityManager());
//自定义拦截器限制并发人数,参考博客
LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
// 验证 token
filtersMap.put("token",new CustomAccessControllerFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// 配置不会被拦截的链接 顺序判断
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/api/login", "anon");
//filterChainDefinitionMap.put("/index/**","anon");
filterChainDefinitionMap.put("/images/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/layui/**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/treetable-lay/**", "anon");
filterChainDefinitionMap.put("/api/user/token", "anon");
//放开swagger-ui地址
filterChainDefinitionMap.put("/swagger/**", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/captcha.jpg", "anon");
filterChainDefinitionMap.put("/","anon");
filterChainDefinitionMap.put("/csrf","anon");
filterChainDefinitionMap.put("/**","token,authc");
//配置shiro默认登录界面地址前后端分离中登录界面跳转应由前端路由控制后台仅返回json数据
shiroFilterFactoryBean.setLoginUrl("/api/login");
//// 设置默认登录的 URL身份认证失败会访问该 URL
//shiroFilterFactoryBean.setLoginUrl("/login");
//// 设置成功之后要跳转的链接
//shiroFilterFactoryBean.setSuccessUrl("/success");
//// 设置未授权界面权限认证失败会访问该 URL
//shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
* @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
* @throws
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
}

View File

@ -1,4 +1,4 @@
package com.lingu.suelec.study.test; package com.suelec.permission.test;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -0,0 +1,41 @@
package com.suelec.permission.utils;
/**
* @ClassName: CodeUtil
* 编码工具类
*/
public class CodeUtil {
private static final String DEPT_TPYE="YXD";
private static final String PERMISSION_TPYE="YXP";
/**
* 右补位左对齐
* @pparam oriStr 原字符串
* @param len 目标字符串长度
* @param alexin 补位字符
* @return 目标字符串
* 以alexin 做为补位
*/
public static String padRight(String oriStr,int len,String alexin){
String str = "";
int strlen = oriStr.length();
if(strlen < len){
for(int i=0;i<len-strlen;i++){
str=str+alexin;
}
}
str=str+oriStr;
return str;
}
/**
* 获取机构编码 YXD0001
* @param oriStr 初始值
 * @param len 位数
 * @param alexin 不足 以什么补充
* @return java.lang.String
*/
public static String deptCode(String oriStr,int len,String alexin){
return DEPT_TPYE+padRight(oriStr, len, alexin);
}
}

View File

@ -0,0 +1,203 @@
package com.suelec.permission.utils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* 上传文件工具类
*/
public class FileUtil {
/**
* 魔数到文件类型的映射集合
*/
public static final Map<String, String> TYPES = new HashMap<>();
static {
// 图片此处只提取前六位作为魔数
//TYPES.put("FFD8FF", "jpg");
//TYPES.put("89504E", "png");
//TYPES.put("474946", "gif");
//TYPES.put("524946", "webp");
TYPES.put("FFD8FFE0", "jpg");
TYPES.put("89504E47", "png");
TYPES.put("47494638", "gif");
TYPES.put("49492A00", "tif");
TYPES.put("424D", "bmp");
TYPES.put("41433130", "dwg"); // CAD
TYPES.put("38425053", "psd");
TYPES.put("7B5C727466", "rtf"); // 日记本
TYPES.put("3C3F786D6C", "xml");
TYPES.put("68746D6C3E", "html");
TYPES.put("44656C69766572792D646174653A", "eml"); // 邮件
TYPES.put("D0CF11E0", "doc");
TYPES.put("D0CF11E0", "xls");//excel2003版本文件
TYPES.put("5374616E64617264204A", "mdb");
TYPES.put("252150532D41646F6265", "ps");
TYPES.put("255044462D312E", "pdf");
TYPES.put("504B0304", "docx");
TYPES.put("504B0304", "xlsx");//excel2007以上版本文件
TYPES.put("52617221", "rar");
TYPES.put("57415645", "wav");
TYPES.put("41564920", "avi");
TYPES.put("2E524D46", "rm");
TYPES.put("000001BA", "mpg");
TYPES.put("000001B3", "mpg");
TYPES.put("6D6F6F76", "mov");
TYPES.put("3026B2758E66CF11", "asf");
TYPES.put("4D546864", "mid");
TYPES.put("1F8B08", "gz");
}
/**
* 根据文件的字节数据获取文件类型
* @param filePath 文件路径
* @return
*/
public static String getFileType(String filePath) throws IOException {
//提取前六位作为魔数
String magicNumberHex = getHex(getFileBytes(filePath), 8);
return TYPES.get(magicNumberHex);
}
/**
* 根据文件的字节数据获取文件类型
* @param data 字节数组形式的文件数据
* @return
*/
public static String getFileType(byte[] data) throws IOException {
//提取前六位作为魔数
String magicNumberHex = getHex(data, 8);
return TYPES.get(magicNumberHex);
}
/**
* 上传文件()
* @param file 文件对象
* @param path 保存路径
* @return
* @throws IOException
*/
public static String upload(MultipartFile file, String path) throws IOException {
String originalFilename = file.getOriginalFilename();// 原文件名称
String date = new SimpleDateFormat("yyyy/MM").format(new Date()).toString();
String fileName = date + "/" + UUID.randomUUID().toString().replace("-","") + originalFilename.substring(originalFilename.lastIndexOf("."));
File dest = new File(path + "/" + fileName);
if (!dest.getParentFile().exists()){
dest.setWritable(true);
dest.getParentFile().mkdirs();
}
file.transferTo(dest);
return fileName;
}
/**
* 上传多张
* @param files file数组
* @param path 保存路径
* @return
*/
public static List<String> upload(MultipartFile[] files, String path) throws IOException {
List<String> imagePathList = new ArrayList<>();
//判断file数组不能为空并且长度大于0
if (files != null && files.length > 0){
String date = new SimpleDateFormat("yyyy/MM").format(new Date()).toString();
// 处理路径并判断目录是否存在
File dir = new File(path + "/" + date);
if (!dir.exists()) {
// 设置写权限
dir.setWritable(true);
dir.mkdirs();
}
for (MultipartFile file : files){
if (!file.isEmpty()){
// 原文件名称
String fileName = file.getOriginalFilename();
String newFileName = date + "/" + UUID.randomUUID().toString().replace("-","") + fileName.substring(fileName.lastIndexOf("."));
file.transferTo(new File(path + "/" + newFileName));
imagePathList.add(newFileName);
}
}
}
return imagePathList;
}
/**
* 删除文件
* @param filePath 文件路径
* @return
*/
public static boolean delete(String filePath){
File file = new File(filePath);
if (file.isFile()){
return file.delete();
}
return false;
}
/**
* 验证文件大小
* @param fileLen 文件大小
* @param fileSize 规定文件大小
* @param fileUnit 单位
* @return
*/
public static boolean checkFileSize(Long fileLen, int fileSize, String fileUnit) {
double fileSizeCom = 0;
if ("B".equals(fileUnit.toUpperCase())) {
fileSizeCom = (double) fileLen;
} else if ("K".equals(fileUnit.toUpperCase())) {
fileSizeCom = (double) fileLen / 1024;
} else if ("M".equals(fileUnit.toUpperCase())) {
fileSizeCom = (double) fileLen / (1024 * 1024);
} else if ("G".equals(fileUnit.toUpperCase())) {
fileSizeCom = (double) fileLen / (1024 * 1024 * 1024);
}
if (fileSizeCom > fileSize) {
return false;
}
return true;
}
/**
* 读取文件字节数据
* @param filePath
* @return
* @throws IOException
*/
private static byte[] getFileBytes(String filePath) throws IOException {
InputStream fs = new FileInputStream(filePath);
byte[] b = new byte[fs.available()];
fs.read(b);
return b;
}
/**
* 获取16进制表示的魔数
* @param data 字节数组形式的文件数据
* @param magicNumberLength 魔数长度
* @return
*/
public static String getHex(byte[] data, int magicNumberLength) {
//提取文件的魔数
StringBuilder magicNumber = new StringBuilder();
//一个字节对应魔数的两位
int magicNumberByteLength = magicNumberLength / 2;
for (int i = 0; i < magicNumberByteLength; i++) {
magicNumber.append(Integer.toHexString(data[i] >> 4 & 0xF));
magicNumber.append(Integer.toHexString(data[i] & 0xF));
}
return magicNumber.toString().toUpperCase();
}
}

View File

@ -0,0 +1,189 @@
package com.suelec.permission.utils;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class FileUtils {
// ================================ 文件上传与删除 ============================
/**
* 上传文件()
* @param file
* @param path
* @return
* @throws IOException
*/
public static String upload(MultipartFile file,String path) throws IOException {
String originalFilename = file.getOriginalFilename();// 原文件名称
File dest = new File(path + "/" + originalFilename);
if (!dest.getParentFile().exists()){
dest.setWritable(true);
dest.getParentFile().mkdirs();
}
file.transferTo(dest);
return originalFilename;
}
/**
* 删除文件
* @param filePath
* @return
*/
public static boolean delete(String filePath){
File file = new File(filePath);
if (file.isFile()){
return file.delete();
}
return false;
}
// ================================ 视频与音频处理 ============================
/**
* 视频转码
* @param ffmpegEXEPath ffmpeg.exx 绝对路径
* @param videoInputPath 视频绝对路径
* @param videoOutputPath 转换后的新视频的绝对路径
* @throws IOException
*/
public static void converVideo(String ffmpegEXEPath,String videoInputPath,String videoOutputPath) throws IOException {
// ffmpeg.exe -i 01.mp4 -y xin.mp4 // -y 是强制覆盖
List<String> commod = new ArrayList<>();
commod.add(ffmpegEXEPath);
commod.add("-i");
commod.add(videoInputPath);
commod.add("-y");
commod.add(videoOutputPath);
// ProcessBuilder 执行一条命令
ProcessBuilder processBuilder = new ProcessBuilder(commod);
Process process = processBuilder.start();
// ffmpeg 进行音频与视频整合或转码时或产生很多流与碎片文件为了防止占用主线程卡主所以使用流的方式
InputStream inputStream = process.getErrorStream();// 获取字节流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);// 字节流转字符流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 吧字符流放到字符流缓冲流中读取
String line = "";
while ((line = bufferedReader.readLine()) != null){};
// 关闭流
if (bufferedReader != null){
bufferedReader.close();
}
if (inputStreamReader != null){
inputStreamReader.close();
}
if (inputStream != null){
inputStream.close();
}
}
/**
* 视频与音频合并
* @param ffmpegEXEPath ffmpeg.exx 绝对路径
* @param videoInputPath 视频绝对路径
* @param mp3InputPath 音频绝对路径
* @param videoSeconds 合并后的视频时长
* @param videoOutputPath 合并后的新视频的绝对路径
* @throws IOException
*/
public static void converMergreVideoMp3(String ffmpegEXEPath, String videoInputPath, String mp3InputPath, double videoSeconds, String videoOutputPath) throws IOException {
// ffmpeg.exe -i 01.mp4 -i bgm.mp3 -t 41 -y xin.mp4 // -y 是强制覆盖
List<String> commod = new ArrayList<>();
commod.add(ffmpegEXEPath);
commod.add("-i");
commod.add(videoInputPath);
commod.add("-i");
commod.add(mp3InputPath);
commod.add("-t");
commod.add(String.valueOf(videoSeconds));
commod.add("-y");
commod.add(videoOutputPath);
// ProcessBuilder 执行一条命令
ProcessBuilder processBuilder = new ProcessBuilder(commod);
Process process = processBuilder.start();
// ffmpeg 进行音频与视频整合或转码时或产生很多流与碎片文件为了防止占用主线程卡主所以使用流的方式
InputStream inputStream = process.getErrorStream();// 获取字节流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);// 字节流转字符流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 吧字符流放到字符流缓冲流中读取
String line = "";
while ((line = bufferedReader.readLine()) != null){};
// 关闭流
if (bufferedReader != null){
bufferedReader.close();
}
if (inputStreamReader != null){
inputStreamReader.close();
}
if (inputStream != null){
inputStream.close();
}
}
/**
* ffmpeg 截图视频封面注意截图时目录必须存在截图并不会自动创建目录
* @param ffmpegEXEPath ffmpeg.exx 绝对路径
* @param videoPath 视频绝对路径
* @param videoCoverOutputPath 保存视频封面的绝对路径
*/
public static void converVideoCover(String ffmpegEXEPath,String videoPath,String videoCoverOutputPath) throws IOException {
// 判断目录是否存在
File file = new File(videoCoverOutputPath);
if (!file.getParentFile().exists()){
file.setWritable(true);
file.getParentFile().mkdirs();
}
// ffmpeg.exe -ss 00:00:01 -y -i 0001.mp4 -vframes 1 0001.jpg // ffmpeg 截图视频封面 -vframes 1 表示截取一帧
List<String> commod = new ArrayList<>();
commod.add(ffmpegEXEPath);
commod.add("-ss");
commod.add("00:00:01");// 默认截图视频 01 秒的一帧
commod.add("-y");
commod.add("-i");
commod.add(videoPath);
commod.add("-vframes");
commod.add("1");// 默认截图一帧
commod.add(videoCoverOutputPath);
// 执行 cmd 命令
ProcessBuilder processBuilder = new ProcessBuilder(commod);
Process process = processBuilder.start();
// ffmpeg 进行音频与视频整合或转码时或产生很多流与碎片文件为了防止占用主线程卡主所以使用流的方式
InputStream inputStream = process.getErrorStream();// 获取字节流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);// 字节流转字符流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 吧字符流放到字符流缓冲流中读取
String line = "";
while ((line = bufferedReader.readLine()) != null){};
// 关闭流
if (bufferedReader != null){
bufferedReader.close();
}
if (inputStreamReader != null){
inputStreamReader.close();
}
if (inputStream != null){
inputStream.close();
}
}
public static void main(String[] args) {
// 测试
String ffmpegEXE = "G:\\ffmpeg\\bin\\ffmpeg.exe";
String videoInputPath = "G:\\ffmpeg\\bin\\01.mp4";
String videoOutputPath = "G:\\ffmpeg\\bin\\01.avi";
String mp3InputPath = "G:\\ffmpeg\\bin\\bgm.mp3";
String videoCoverPath = "G:\\ffmpeg\\bin\\001\\0001.jpg";
String conver = "G:/video-upload/1230681055802642432/cover/wx993172f7da9acf1f.jpg";
try {
//converVideo(ffmpegEXE,videoInputPath,videoOutputPath);// 视频格式转换
//converMergreVideoMp3(ffmpegEXE,videoInputPath,mp3InputPath,7,videoOutputPath);// 视频与音频整合
converVideoCover(ffmpegEXE,videoInputPath,conver);// 截图视频封面
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,161 @@
package com.suelec.permission.utils;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
/**
* <p>名称IdWorker.java</p>
* <p>描述分布式自增长ID</p>
* <pre>
* Twitter的 Snowflake JAVA实现方案
* </pre>
* 核心代码为其IdWorker这个类实现其原理结构如下我分别用一个0表示一位分割开部分的作用
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
* 在上面的字符串中第一位为未使用实际上也可作为long的符号位接下来的41位为毫秒级时间
* 然后5位datacenter标识位5位机器ID并不算标识符实际是为线程标识
* 然后12位该毫秒内的当前毫秒内的计数加起来刚好64位为一个Long型
* 这样的好处是整体上按照时间自增排序并且整个分布式系统内不会产生ID碰撞由datacenter和机器ID作区分
* 并且效率较高经测试snowflake每秒能够产生26万ID左右完全满足需要
* <p>
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
*
* @author Polim
*/
public class IdWorker {
// 时间起始标记点作为基准一般取系统的最近时间一旦确定不能变动
private final static long twepoch = 1288834974657L;
// 机器标识位数
private final static long workerIdBits = 5L;
// 数据中心标识位数
private final static long datacenterIdBits = 5L;
// 机器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 数据中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 毫秒内自增位
private final static long sequenceBits = 12L;
// 机器ID偏左移12位
private final static long workerIdShift = sequenceBits;
// 数据中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits;
// 时间毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
/* 上次生产id时间戳 */
private static long lastTimestamp = -1L;
// 0并发控制
private long sequence = 0L;
private final long workerId;
// 数据标识id部分
private final long datacenterId;
public IdWorker(){
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
/**
* @param workerId
* 工作机器ID
* @param datacenterId
* 序列号
*/
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* 获取下一个ID
*
* @return
*/
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
// 当前毫秒内+1
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 当前毫秒内计数满了则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// ID偏移组合生成最终的ID并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
/**
* <p>
* 获取 maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (!name.isEmpty()) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
* MAC + PID hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
/**
* <p>
* 数据标识id部分
* </p>
*/
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage());
}
return id;
}
}

View File

@ -0,0 +1,199 @@
package com.suelec.permission.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.CompressionCodecs;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
/**
* jwt token 工具类
*/
public class JwtTokenUtil {
/**
* 实例
*/
private static JwtTokenUtil instance;
/**
* 发行者
*/
private String issuer;
/**
* 主体subject 代表这个JWT的主体即它的所有人 一般是用户id
*/
private String subObject;
/**
* 过期时间默认7天
*/
private long expired = 1000 * 60 * 60 * 24 * 7;
/**
* jwt构造
*/
private static JwtBuilder jwtBuilder;
/**
* 密钥
*/
private String secret;// 密钥
/**
* 获取实例
* @return
*/
public static JwtTokenUtil getInstance(){
if (instance == null){
instance = new JwtTokenUtil();
}
jwtBuilder = Jwts.builder();
return instance;
}
/**
* 荷载信息(通常是一个User信息还包括一些其他的元数据)
* @param key
* @param val
* @return
*/
public JwtTokenUtil setClaim(String key, Object val){
jwtBuilder.claim(key,val);
return this;
}
/**
* 生成 jwt token
* @return
*/
public String generateToken(){
String token = jwtBuilder
.setIssuer(issuer)// 发行者
.setSubject(subObject) // 主体
//.claim("id","121") // 参数
.setIssuedAt(new Date()) // 发行时间
.setExpiration(new Date(System.currentTimeMillis() + expired))
.signWith(SignatureAlgorithm.HS256,secret) // 签名类型 密钥
.compressWith(CompressionCodecs.DEFLATE)// 对载荷进行压缩
.compact(); // 压缩一下
return token;
}
/**
* 解析 token
* @param token
* @return
*/
public Claims parseToken(String token){
try{
final Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
return claims;
}catch (Exception e){}
return null;
}
/**
* 验证是否过期
* @param token
* @return
*/
public boolean isTokenExpired(String token){
try{
Claims claims = parseToken(token);
return claims != null && !claims.getExpiration().before(new Date());
}catch (Exception e){
return true;
}
}
/**
* 验证token是否验证通过
* @param token
* @return
*/
public boolean checkToken(String token){
try{
return isTokenExpired(token);
}catch (Exception e){
return false;
}
}
/**
* 获取用户id
* @param token
* @return
*/
public String getUserId(String token){
try{
Claims claims = parseToken(token);
return claims != null ? claims.getSubject() : null;
}catch (Exception e){
return null;
}
}
/**
* 获取token的剩余过期时间
* @param token
* @return
*/
public long getRemainingTime(String token){
long time = 0;
try{
Claims claims = parseToken(token);
time = claims.getExpiration().getTime() - System.currentTimeMillis();
}catch (Exception e){}
return time;
}
/**
* 设置发行者
* @param issuer
* @return
*/
public JwtTokenUtil setIssuer(String issuer) {
this.issuer = issuer;
return this;
}
/**
* 设置主题
* @param subObject
* @return
*/
public JwtTokenUtil setSubObject(String subObject) {
this.subObject = subObject;
return this;
}
public long getExpired() {
return expired;
}
/**
* 设置过期时间
* @param expired
* @return
*/
public JwtTokenUtil setExpired(long expired) {
this.expired = expired;
return this;
}
/**
* 设置密钥
* @param secret
* @return
*/
public JwtTokenUtil setSecret(String secret) {
this.secret = secret;
return this;
}
}

View File

@ -0,0 +1,28 @@
package com.suelec.permission.utils;
import com.github.pagehelper.PageInfo;
import com.suelec.permission.vo.resp.PageVo;
/**
* 分页工具类
*/
public class PageUtil {
/**
* 分页数据组装
* @param pageInfo
* @param <T>
* @return
*/
public static <T>PageVo<T> getPageVo(PageInfo<T> pageInfo){
PageVo<T> pageInfoPageVo = new PageVo<T>();
pageInfoPageVo.setTotalRows(pageInfo.getTotal());//总记录数
pageInfoPageVo.setTotalPages(pageInfo.getPages());//总页数
pageInfoPageVo.setPageNum(pageInfo.getPageNum());//当前第几页
pageInfoPageVo.setPageSize(pageInfo.getPageSize());//每页记录数
pageInfoPageVo.setCurPageSize(pageInfo.getSize());//当前页记录数
pageInfoPageVo.setRows(pageInfo.getList());//结果集
return pageInfoPageVo;
}
}

View File

@ -0,0 +1,76 @@
package com.suelec.permission.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
/**
* 返回数据类
* @param <T>
*/
//保证序列化json的时候,如果是null的对象,key也会消失
//@JsonInclude(Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response<T> implements Serializable {
// 成功值
private static final int SUCCESS_CODE = 1;
// 失败值
private static final int ERROR_CODE = 0;
//状态码
private int code;
//消息
private String msg;
//返回数据
private T data;
private Response(int code){
this.code = code;
}
private Response(int code,T data){
this.code = code;
this.data = data;
}
private Response(int code,String msg){
this.code = code;
this.msg = msg;
}
private Response(int code,String msg,T data){
this.code = code;
this.msg = msg;
this.data = data;
}
public static <T> Response<T> success(){
return new Response<T>(SUCCESS_CODE,"success");
}
public static <T> Response<T> success(String msg){
return new Response<T>(SUCCESS_CODE,msg);
}
public static <T> Response<T> success(T data){
return new Response<T>(SUCCESS_CODE,data);
}
public static <T> Response<T> success(String msg,T data){
return new Response<T>(SUCCESS_CODE,msg,data);
}
public static <T> Response<T> error(){
return new Response<T>(ERROR_CODE,"error");
}
public static <T> Response<T> error(String msg){
return new Response<T>(ERROR_CODE,msg);
}
public static <T> Response<T> error(int code,String msg){
return new Response<T>(code,msg);
}
public int getCode(){
return code;
}
public String getMsg(){
return msg;
}
public T getData(){
return data;
}
}

View File

@ -0,0 +1,26 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class LogPageReqVo {
@ApiModelProperty("当前页数")
private Integer pageNum=1;
@ApiModelProperty(value = "当前页的数量")
private int pageSize=10;
@ApiModelProperty(value = "用户操作动作")
private String operation;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "开始时间")
private String startTime;
@ApiModelProperty(value = "结束时间")
private String endTime;
}

View File

@ -0,0 +1,26 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
@Data
@ApiModel(value = "登陆对象",description = "用户登陆的参数对象")
public class LoginReqVo {
@ApiModelProperty(value = "账号")
@NotBlank(message = "账号不能为空")
@Length(min = 3,max = 16,message = "账号名称长度需要在3~16个字之间")
private String username;
@ApiModelProperty(value = "密码")
@NotBlank(message = "密码不能为空")
private String password;
@ApiModelProperty(value = "登录类型 1pc2App")
@NotBlank(message = "用户登录类型不能为空")
private String type;
}

View File

@ -0,0 +1,48 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class PermissionAddReqVo {
@ApiModelProperty(value = "菜单权限名称")
@NotBlank(message = "菜单权限名称不能为空")
private String title;
@ApiModelProperty(value = "菜单图标icon")
private String icon;
@ApiModelProperty(value = "菜单权限标识shiro 适配restful")
private String perms;
@ApiModelProperty(value = "接口地址")
private String url;
@ApiModelProperty(value = "请求方式 和url 配合使用 (我们用 路径匹配的方式做权限管理的时候用到)")
private String method;
@ApiModelProperty(value = "name与前端vue路由name约定一致")
private String name;
@ApiModelProperty(value = "父级id")
@NotNull(message = "所属菜单不能为空")
private String pid;
@ApiModelProperty(value = "排序码")
private Integer orderNum;
@ApiModelProperty(value = "菜单权限类型(1:目录;2:菜单;3:按钮)")
@NotNull(message = "菜单权限类型不能为空")
private Integer type;
@ApiModelProperty(value = "状态1:正常 0禁用")
private Integer status;
@ApiModelProperty(value = "编码(前后端分离 前段对按钮显示隐藏控制 btn-permission-search 代表 菜单权限管理的列表查询按钮)")
private String code;
}

View File

@ -0,0 +1,47 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class PermissionUpdateReqVo {
@ApiModelProperty(value = "id")
@NotBlank(message = "id 不能为空")
private String id;
@ApiModelProperty(value = "状态1:正常 0禁用")
private Integer status;
@ApiModelProperty(value = "菜单权限名称")
private String title;
@ApiModelProperty(value = "菜单图标icon")
private String icon;
@ApiModelProperty(value = "菜单权限标识shiro 适配restful")
private String perms;
@ApiModelProperty(value = "接口地址")
private String url;
@ApiModelProperty(value = "请求方式 和url 配合使用 (我们用 路径匹配的方式做权限管理的时候用到)")
private String method;
@ApiModelProperty(value = "name与前端vue路由name约定一致")
private String name;
@ApiModelProperty(value = "父级id")
private String pid;
@ApiModelProperty(value = "排序码")
private Integer orderNum;
@ApiModelProperty(value = "菜单权限类型(1:目录;2:菜单;3:按钮)")
private Integer type;
@ApiModelProperty(value = "编码(前后端分离 前段对按钮显示隐藏控制 btn-permission-search 代表 菜单权限管理的列表查询按钮)")
private String code;
}

View File

@ -0,0 +1,25 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class RolePageReqVo {
@ApiModelProperty(value = "第几页")
private int pageNum=1;
@ApiModelProperty(value = "当前页的数量")
private int pageSize=10;
@ApiModelProperty(value = "角色id")
private String roleId;
@ApiModelProperty(value = "角色名称")
private String roleName;
@ApiModelProperty(value = "角色状态")
private Integer status;
@ApiModelProperty(value = "开始时间")
private String startTime;
@ApiModelProperty(value = "结束时间")
private String endTime;
}

View File

@ -0,0 +1,20 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
@Data
public class RolePermissionOperationReqVo {
@ApiModelProperty(value = "角色id")
@NotBlank(message = "角色id不能为空")
private String roleId;
@ApiModelProperty(value = "菜单权限集合id")
@NotBlank(message = "菜单权限集合不能为空")
private List<String> permissionIds;
}

View File

@ -0,0 +1,26 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import java.util.List;
@Data
public class RoleReqVo {
@ApiModelProperty(value = "角色名称")
@NotBlank(message = "角色名称不能为空")
@Length(min = 2,max = 15,message = "角色名称长度为2 ~ 15个字符")
private String name;
@ApiModelProperty(value = "角色描述")
private String description;
@ApiModelProperty(value = "角色状态1:正常0:弃用")
private Integer status;
@ApiModelProperty(value = "选择的菜单id集合")
private List<String> permissionsIds;
}

View File

@ -0,0 +1,27 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
@Data
public class RoleUpdateReqVo {
@ApiModelProperty(value = "角色id")
@NotBlank(message = "角色 id 不能为空")
private String id;
@ApiModelProperty(value = "角色名称")
private String name;
@ApiModelProperty(value = "角色描述")
private String description;
@ApiModelProperty(value = "状态(1:正常0:弃用)")
private Integer status;
@ApiModelProperty(value = "所拥有的菜单权限")
private List<String> permissionsIds;
}

View File

@ -0,0 +1,39 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class UserAddReqVo {
@ApiModelProperty(value = "账号")
@NotBlank(message = "账号不能为空")
private String username;
@ApiModelProperty(value = "密码")
@NotBlank(message = "密码不能为空")
private String password;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "昵称")
private String nickName;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "性别")
private Integer sex;
@ApiModelProperty(value = "创建来源(1.web 2.android 3.ios )")
private String createWhere;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 )")
private Integer status;
}

View File

@ -0,0 +1,19 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
@Data
public class UserOwnRoleReqVo {
@ApiModelProperty(value = "用户id")
@NotBlank(message = "用户id不能为空")
private String userId;
@ApiModelProperty(value = "赋予用户的角色id集合")
private List<String> roleIds;
}

View File

@ -0,0 +1,29 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class UserPageReqVo {
@ApiModelProperty(value = "当前第几页")
private Integer pageNum=1;
@ApiModelProperty(value = "当前页数量")
private Integer pageSize=10;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "昵称")
private String nickName;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 ")
private Integer status;
@ApiModelProperty(value = "开始时间")
private String startTime;
@ApiModelProperty(value = "结束时间")
private String endTime;
}

View File

@ -0,0 +1,21 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "用户编辑对象",description = "用户编辑信息对象")
@Data
public class UserUpdateDetailInfoReqVo {
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "性别(1.男 2.女)")
private Integer sex;
@ApiModelProperty(value = "真实名称")
private String realName;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 )")
private Integer status;
}

View File

@ -0,0 +1,19 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@ApiModel(value = "修改密码对象",description = "编辑密码对象")
@Data
public class UserUpdatePasswordReqVo {
@ApiModelProperty(value = "旧密码")
@NotBlank(message = "旧密码不能为空")
private String oldPwd;
@ApiModelProperty(value = "新密码")
@NotBlank(message = "新密码不能为空")
private String newPwd;
}

View File

@ -0,0 +1,41 @@
package com.suelec.permission.vo.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class UserUpdateReqVo {
@ApiModelProperty(value = "用户id")
@NotBlank(message = "用户id不能为空")
private String id;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "昵称")
private String nickName;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "性别")
private Integer sex;
@ApiModelProperty(value = "创建来源(1.web 2.android 3.ios )")
private Integer createWhere;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 )")
private Integer status;
}

View File

@ -0,0 +1,17 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel(value = "首页数据对象",description = "首页展示数据对象")
@Data
public class HomeRespVo {
@ApiModelProperty(value = "用户信息")
private UserRespVo userInfo;
@ApiModelProperty(value = "权限菜单")
private List<PermissionRespNodeVo> menus;
}

View File

@ -0,0 +1,31 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class LoginRespVo {
@ApiModelProperty(value = "正常的业务token")
private String authorization;
@ApiModelProperty(value = "用户id")
private String id;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "昵称")
private String nickname;
@ApiModelProperty(value = "权限菜单集合")
private List<PermissionRespNodeVo> menus;
@ApiModelProperty(value = "按钮权限集合")
private List<String> permissions;
}

View File

@ -0,0 +1,43 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class PageVo<T> {
/**
* 总记录数
*/
@ApiModelProperty(value = "总记录数")
private Long totalRows;
/**
* 总页数
*/
@ApiModelProperty(value = "总页数")
private Integer totalPages;
/**
* 当前第几页
*/
@ApiModelProperty(value = "当前第几页")
private Integer pageNum;
/**
* 每页记录数
*/
@ApiModelProperty(value = "每页记录数")
private Integer pageSize;
/**
* 当前页记录数
*/
@ApiModelProperty(value = "当前页记录数")
private Integer curPageSize;
/**
* 数据列表
*/
@ApiModelProperty(value = "数据列表")
private List<T> rows;
}

View File

@ -0,0 +1,17 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PermissionRespNodeTreeVo {
@ApiModelProperty(value = "权限id")
private String id;
@ApiModelProperty(value = "菜单权限名称")
private String title;
@ApiModelProperty(value = "level几级子菜单")
private int level;
}

View File

@ -0,0 +1,37 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class PermissionRespNodeVo {
@ApiModelProperty(value = "权限id")
private String id;
@ApiModelProperty(value = "菜单权限名称")
private String title;
@ApiModelProperty(value = "菜单权限图标")
private String icon;
@ApiModelProperty(value = "菜单地址")
private String path;
@ApiModelProperty(value = "菜单name")
private String name;
@ApiModelProperty(value = "是否是菜单")
private boolean menu;
@ApiModelProperty(value = "子集集合")
private List<PermissionRespNodeVo> children;
/*@ApiModelProperty(value = "默认展开")
private boolean spread=true;*/
/* @ApiModelProperty(value = "节点是否选中")
private boolean checked;*/
}

View File

@ -0,0 +1,33 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
// TODO: vue中废弃不用
@Data
public class RoleDetailInfoRespVo implements Serializable {
@ApiModelProperty(value = "角色id")
private String id;
@ApiModelProperty(value = "角色名称")
private String name;
@ApiModelProperty(value = "角色描述")
private String description;
@ApiModelProperty(value = "角色状态")
private Integer status;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@ApiModelProperty(value = "角色拥有的权限结构数据")
private List<PermissionRespNodeVo> permissionRespNode;
}

View File

@ -0,0 +1,17 @@
package com.suelec.permission.vo.resp;
import com.suelec.permission.pojo.SysRole;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class UserOwnRoleRespVo {
@ApiModelProperty(value = "用户拥有的权限ids")
private List<String> ownRoleIds;
@ApiModelProperty(value = "所有权限")
private List<SysRole> allRole;
}

View File

@ -0,0 +1,33 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "用户对象",description = "用户信息对象")
@Data
public class UserRespVo {
@ApiModelProperty(value = "用户id")
private String id;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "昵称")
private String nickName;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "性别(1.男 2.女)")
private Integer sex;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 )")
private Integer status;
@ApiModelProperty(value = "邮箱(唯一)")
private String email;
}

View File

@ -0,0 +1,50 @@
package com.suelec.permission.vo.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ApiModel(value = "用户表格对象",description = "用户信息对象")
@Data
public class UserTableRespVo {
@ApiModelProperty(value = "用户id")
private String id;
@ApiModelProperty(value = "账号")
private String username;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "昵称")
private String nickName;
@ApiModelProperty(value = "真实姓名")
private String realName;
@ApiModelProperty(value = "性别(1.男 2.女)")
private Integer sex;
@ApiModelProperty(value = "账户状态(1.正常 2.锁定 )")
private Integer status;
@ApiModelProperty(value = "邮箱(唯一)")
private String email;
@ApiModelProperty(value = "创建人名称")
private String createUserName;
@ApiModelProperty(value = "更新人名称")
private String updateUserName;
@ApiModelProperty(value = "创建来源")
private Integer createWhere;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -1,7 +1,9 @@
package com.lingu.suelec.study.controller; package com.suelec.trainclass.controller;
import com.lingu.suelec.study.service.TrainService; import com.suelec.trainclass.service.TrainService;
import org.springframework.beans.factory.annotation.Autowired; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -10,33 +12,27 @@ import javax.annotation.Resource;
@RestController @RestController
@RequestMapping @RequestMapping
@Api(value = "培训班接口")
//@Api(value = "培训班接口")
public class TrainController { public class TrainController {
@Resource @Resource
TrainService trainService; TrainService trainService;
@RequestMapping("test")
public String test(){
return "11";
}
/** /**
* 我的收藏-培训班 * 我的收藏-培训班
* @param id * @param id
* @return * @return
*/ */
//@ApiOperation("培训班查询") @ApiOperation("培训班查询")
@RequestMapping("selectTrainInfo") @PostMapping("selectTrainInfo")
public Object selectTrainInfo(@RequestParam String id){ public Object selectTrainInfo(@RequestParam String id){
return trainService.selectTrainInfo(id); return trainService.selectTrainInfo(id);
} }
//@ApiOperation("培训班查询") @ApiOperation("培训班查询")
@RequestMapping("selectTtrainClassList") @PostMapping("selectTtrainClassList")
public Object selectTtrainClassList(String id){ public Object selectTtrainClassList(String id){
return trainService.selectTtrainClassList(id); return trainService.selectTtrainClassList(id);
} }

View File

@ -0,0 +1,13 @@
package com.suelec.trainclass.dao;
import com.suelec.trainclass.pojo.TrainInfo;
import java.util.List;
public interface TrainDao {
TrainInfo selectTrainInfo(String userId);
List<TrainInfo> selectTtrainClassList();
}

View File

@ -1,8 +1,9 @@
package com.lingu.suelec.study.domain; package com.suelec.trainclass.pojo;
import lombok.Data; import lombok.Data;
import java.util.Date; import java.util.Date;
@Data @Data
public class TrainInfo { public class TrainInfo {
// //

View File

@ -1,4 +1,4 @@
package com.lingu.suelec.study.domain; package com.suelec.trainclass.pojo;
import lombok.Data; import lombok.Data;

View File

@ -0,0 +1,11 @@
package com.suelec.trainclass.service;
import com.suelec.trainclass.pojo.TrainInfo;
import java.util.List;
public interface TrainService {
TrainInfo selectTrainInfo(String id);
List<TrainInfo> selectTtrainClassList(String id);
}

Some files were not shown because too many files have changed in this diff Show More