Commit d9b4a048 authored by AfirSraftGarrier's avatar AfirSraftGarrier

Merge branch 'for-yx'

# Conflicts:
#	license/pom.xml
#	license/src/main/java/iot/sixiang/license/controller/SysOperLogController.java
#	license/src/main/java/iot/sixiang/license/controller/UserController.java
#	license/src/main/java/iot/sixiang/license/handler/GlobalExceptionHandler.java
#	license/src/main/java/iot/sixiang/license/mapper/SysOperLogMapper.java
#	license/src/main/java/iot/sixiang/license/net/TcpClient.java
#	license/src/main/java/iot/sixiang/license/service/SysOperLogService.java
#	license/src/main/java/iot/sixiang/license/service/UserService.java
#	license/src/main/java/iot/sixiang/license/service/impl/SysOperLogServiceImpl.java
#	license/src/main/java/iot/sixiang/license/service/impl/UserServiceImpl.java
#	license/src/main/java/iot/sixiang/license/util/CommonUtil.java
#	license/src/main/resources/mapper/PmsUseLogMapper.xml
#	license/src/main/resources/mapper/SysOperLogMapper.xml
parents 0e466f24 cdff0268
......@@ -33,3 +33,5 @@ build/
.vscode/
*-acc.yml
logs
\ No newline at end of file
......@@ -15,7 +15,6 @@
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<acc.log.version>1.0.2</acc.log.version>
</properties>
<dependencies>
......@@ -82,7 +81,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.4</version>
<version>2.0.9</version>
</dependency>
<dependency>
......@@ -102,31 +101,83 @@
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.acc</groupId>
<artifactId>log</artifactId>
<version>${acc.log.version}</version>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.8.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
<!--邮件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.sixiang.iot</groupId>
<artifactId>server-license</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/Safety.jar</systemPath>
</dependency>
<dependency>
<groupId>com.acc</groupId>
<artifactId>secret</artifactId>
<version>1.0.5</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/secret-1.0.5.jar</systemPath>
</dependency>
<repositories>
<repository>
<id>maven-releases</id>
<url>http://120.24.220.98:8868/repository/maven-public/</url>
</repository>
</repositories>
</dependencies>
<build>
<finalName>license</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 打包时包含引入的外部jar包 -->
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
......
......@@ -4,17 +4,16 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableAsync
@ServletComponentScan(basePackages = "iot.sixiang.license")
@SpringBootApplication
@EnableScheduling
@MapperScan(basePackages = "iot.sixiang.license.mapper")
@ComponentScan(basePackages = {"iot.sixiang.license", "com.acc"})
public class LicenseApplication implements WebMvcConfigurer {
@Override
......
......@@ -54,5 +54,4 @@ public class BalanceManager {
return servers.get(index);
}
}
}
......@@ -3,6 +3,7 @@ package iot.sixiang.license.config;
import iot.sixiang.license.jwt.AuthenticationInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
......@@ -14,11 +15,17 @@ public class CorsConfig implements WebMvcConfigurer {
@Autowired
AuthenticationInterceptor authenticationInterceptor;
@Value("${cros.cros_allowed_origins}")
private String[] allowedOrigins;
@Value("${cros.cros_allowed_method}")
private String[] allowedMethods;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedOrigins(allowedOrigins)
.allowedMethods(allowedMethods)
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
......
package iot.sixiang.license.config;
/**
* Title: ThreadPoolConfig
* Description:
*
* @author tianlai3
* @date 2022-07-16 20:05:38
*/
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Data
@Configuration
@EnableAsync
public class ThreadPoolConfig {
private static final int corePoolSize = 1; // 核心线程数(默认线程数)
private static final int maxPoolSize = 2; // 最大线程数
private static final int keepAliveTime = 10; // 允许线程空闲时间(单位:默认为秒)
private static final int queueCapacity = 2; // 缓冲队列数
/**
* 默认异步线程池
*
* @return
*/
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setThreadNamePrefix("threadPoll-");
pool.setCorePoolSize(corePoolSize);
pool.setMaxPoolSize(maxPoolSize);
pool.setKeepAliveSeconds(keepAliveTime);
pool.setQueueCapacity(queueCapacity);
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
pool.initialize();
return pool;
}
}
......@@ -16,7 +16,10 @@ import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.PageResult;
import iot.sixiang.license.model.vo.AppVo;
import iot.sixiang.license.service.ApplyService;
import iot.sixiang.license.xss.XssUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
......@@ -37,18 +40,24 @@ public class ApplyController {
@Autowired
private ApplyService applyService;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
/**
* 添加apply
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "应用添加接口", notes = "用于添加应用")
@PostMapping("add")
@MyLog(title = "添加应用", optParam = "#{jsonObject}", businessType = BusinessType.INSERT)
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject",properties = {
@DynamicParameter(name = "appName",value = "应用名",required = true,dataTypeClass = String.class),
@DynamicParameter(name = "appKey",value = "应用key",required = true,dataTypeClass = String.class),
@DynamicParameter(name = "userId",value = "用户Id",required = true,dataTypeClass = Integer.class)
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "appName", value = "应用名", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "appKey", value = "应用key", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "userId", value = "用户Id", required = true, dataTypeClass = Integer.class)
}))
public BaseResult addApply(@RequestBody JSONObject jsonObject) {
String appName = jsonObject.getString("appName");
......@@ -64,6 +73,7 @@ public class ApplyController {
/**
* 分页查询所有的apply
*
* @param pageNo
* @param pageSize
* @return
......@@ -72,21 +82,26 @@ public class ApplyController {
@GetMapping("list")
@MyLog(title = "获取应用列表", optParam = "#{pageNo},#{pageSize},#{appName}", businessType = BusinessType.SELECT)
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo",value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize",value = "每页显示多少页", required = true, dataType = "int"),
@ApiImplicitParam(name = "appName",value = "应用名")
@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "每页显示多少页", required = true, dataType = "int"),
@ApiImplicitParam(name = "appName", value = "应用名")
})
public PageResult<AppVo> getAppList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo,
@RequestParam(value = "pageSize", defaultValue = "0") int pageSize,
@RequestParam(value = "appName",required = false) String appName) {
PageInfoModel<AppVo> records = applyService.getAppList(pageNo,pageSize,appName);
@RequestParam(value = "appName", required = false) String appName) {
appName = XssUtil.checkXSS(appName);
PageInfoModel<AppVo> records = applyService.getAppList(pageNo, pageSize, appName);
int total = records.getTotal();
int pages = total/pageSize;//pages为总页数
int mod = total%pageSize;
if(mod!=0){
pages = pages +1;
int pages = total / pageSize;//pages为总页数
int mod = total % pageSize;
if (mod != 0) {
pages = pages + 1;
}
List<AppVo> result = records.getResult();
return new PageResult(200,"查找成功",pageNo,pages,total,result);
String str = "n647dBvogC5ps9r0zePShkExRMGyIZlqFUuWNL1Qt8XVja3A";
for (AppVo u : result) {
u.setAppKey(DigestUtils.md5DigestAsHex(((str + u.getAppKey()).getBytes())));
}
return new PageResult(200, "查找成功", pageNo, pages, total, result);
}
}
\ No newline at end of file
......@@ -5,7 +5,10 @@ import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import io.swagger.annotations.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.device.DeviceManager;
import iot.sixiang.license.entity.DeviceBlack;
import iot.sixiang.license.log.BusinessType;
......@@ -17,8 +20,16 @@ import iot.sixiang.license.model.vo.DeviceDetailVo;
import iot.sixiang.license.model.vo.DeviceVo;
import iot.sixiang.license.service.DeviceBlackService;
import iot.sixiang.license.service.DeviceService;
import iot.sixiang.license.xss.XssUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
......@@ -43,6 +54,11 @@ public class DeviceController {
@Autowired
private DeviceBlackService deviceBlackService;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
/**
* 添加device
*
......@@ -51,10 +67,7 @@ public class DeviceController {
*/
@ApiOperation(value = "添加设备接口", notes = "用于添加设备")
@PostMapping("add")
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "appId", value = "应用Id", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "count", value = "需要创建的设备数量", required = true, dataTypeClass = Integer.class),
}))
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {@DynamicParameter(name = "appId", value = "应用Id", required = true, dataTypeClass = String.class), @DynamicParameter(name = "count", value = "需要创建的设备数量", required = true, dataTypeClass = Integer.class),}))
@MyLog(title = "添加设备", optParam = "#{jsonObject}", businessType = BusinessType.INSERT)
public BaseResult addDevice(@RequestBody JSONObject jsonObject) {
String appId = jsonObject.getString("appId");
......@@ -93,6 +106,8 @@ public class DeviceController {
@RequestParam(value = "userName", required = false) String userName,
@RequestParam(value = "sn", required = false) String sn,
@RequestParam(value = "status", required = false) Integer status) {
appName = XssUtil.checkXSS(appName);
userName = XssUtil.checkXSS(userName);
PageInfoModel<DeviceVo> records = deviceService.getDeviceList(pageNo, pageSize, appName, userName, sn, status);
int total = records.getTotal();
int pages = total / pageSize;//pages为总页数
......@@ -107,17 +122,10 @@ public class DeviceController {
@ApiOperation(value = "获取设备详细信息接口", notes = "用于获取设备详细信息列表")
@GetMapping("detail/list")
@MyLog(title = "获取设备详细信息接口", optParam = "#{pageNo},#{pageSize},#{appName},#{userName}", businessType = BusinessType.SELECT)
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "每页显示多少条", required = true, dataType = "int"),
@ApiImplicitParam(name = "appName", value = "应用名"),
@ApiImplicitParam(name = "userName", value = "用户名")
})
public PageResult<DeviceDetailVo> getDeviceDetailList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo,
@RequestParam(value = "pageSize", defaultValue = "0") int pageSize,
@RequestParam(value = "appName", required = false) String appName,
@RequestParam(value = "userName", required = false) String userName) {
@ApiImplicitParams({@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"), @ApiImplicitParam(name = "pageSize", value = "每页显示多少条", required = true, dataType = "int"), @ApiImplicitParam(name = "appName", value = "应用名"), @ApiImplicitParam(name = "userName", value = "用户名")})
public PageResult<DeviceDetailVo> getDeviceDetailList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo, @RequestParam(value = "pageSize", defaultValue = "0") int pageSize, @RequestParam(value = "appName", required = false) String appName, @RequestParam(value = "userName", required = false) String userName) {
appName = XssUtil.checkXSS(appName);
userName = XssUtil.checkXSS(userName);
PageInfoModel<DeviceDetailVo> records = deviceManager.getDeviceDetailList(pageNo, pageSize, appName, userName);
int total = records.getTotal();
int pages = total / pageSize;//pages为总页数
......@@ -137,9 +145,7 @@ public class DeviceController {
*/
@ApiOperation(value = "添加设备黑名单接口", notes = "用于添加设备黑名单")
@PostMapping("device_black/add")
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "deviceId", value = "设备Id", required = true, dataTypeClass = Integer.class)
}))
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {@DynamicParameter(name = "deviceId", value = "设备Id", required = true, dataTypeClass = Integer.class)}))
@MyLog(title = "添加设备黑名单", optParam = "#{jsonObject}", businessType = BusinessType.INSERT)
public BaseResult addDeviceBlack(@RequestBody JSONObject jsonObject) {
int deviceId = jsonObject.getIntValue("deviceId");
......@@ -159,9 +165,7 @@ public class DeviceController {
*/
@ApiOperation(value = "设备黑名单删除接口", notes = "删除设备黑名单")
@PostMapping("device_black/delete")
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "deviceId", value = "设备Id", required = true, dataTypeClass = Integer.class)
}))
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {@DynamicParameter(name = "deviceId", value = "设备Id", required = true, dataTypeClass = Integer.class)}))
@MyLog(title = "删除设备黑名单", optParam = "#{deviceId}", businessType = BusinessType.DELETE)
public BaseResult deleteDeviceBlack(@RequestBody JSONObject jsonObject) {
int deviceId = jsonObject.getIntValue("deviceId");
......@@ -183,10 +187,7 @@ public class DeviceController {
@ApiOperation(value = "获取设备黑名单列表接口", notes = "用于获取设备黑名单列表")
@GetMapping("device_black/list")
@MyLog(title = "获取设备黑名单列表", optParam = "#{pageNo},#{pageSize}", businessType = BusinessType.SELECT)
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "每页显示多少页", required = true, dataType = "int")
})
@ApiImplicitParams({@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"), @ApiImplicitParam(name = "pageSize", value = "每页显示多少页", required = true, dataType = "int")})
public PageResult<DeviceBlack> getDeviceBlackList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo, @RequestParam(value = "pageSize", defaultValue = "0") int pageSize) {
PageInfoModel<DeviceBlack> records = deviceBlackService.getDeviceBlackList(pageNo, pageSize);
int total = records.getTotal();
......
package iot.sixiang.license.controller;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.model.ResResult;
import iot.sixiang.license.model.vo.EncryptVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
/**
* Title: EncryptController
* Description: TODO
*
* @author tianlai3
* @date 2022-07-13 01:05:23
*/
@Slf4j
@RestController
@RequestMapping("/iot_license")
@Api(value = "数据加密", tags = {"数据加密"})
public class EncryptController {
@Value("${other.sm4-key}")
private String sm4Key;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
@ApiOperation(value = "数据加密")
@PostMapping("/encrypt")
public ResResult<EncryptVo> encrypt(@RequestBody EncryptVo encryptVo) {
if (StringUtils.isEmpty(encryptVo.getMessage())) {
return ResResult.failed().setMsgValue("输入的信息不能为空");
}
SM4 sm4 = SmUtil.sm4(sm4Key.getBytes());
EncryptVo vo = new EncryptVo();
vo.setMessage(sm4.encryptBase64(encryptVo.getMessage()));
return ResResult.success().goRecord(vo);
}
@ApiOperation(value = "数据解密")
@PostMapping("/decrypt")
public ResResult<EncryptVo> decrypt(@RequestBody EncryptVo encryptVo) {
if (StringUtils.isEmpty(encryptVo.getMessage())) {
return ResResult.failed().setMsgValue("输入的信息不能为空");
}
SM4 sm4 = SmUtil.sm4(sm4Key.getBytes());
String message = sm4.decryptStr(encryptVo.getMessage());
EncryptVo vo = new EncryptVo();
vo.setMessage(message);
return ResResult.success().goRecord(vo);
}
}
package iot.sixiang.license.controller;
import cn.hutool.core.util.IdcardUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.model.ResResult;
import iot.sixiang.license.model.vo.MaskingVo;
import iot.sixiang.license.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.owasp.esapi.ESAPI;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
/**
* Title: MaskingController
* Description: TODO
*
* @author tianlai3
* @date 2022-07-13 01:40:24
*/
@Slf4j
@RestController
@RequestMapping("/iot_license")
@Api(value = "数据脱敏", tags = {"数据脱敏"})
public class MaskingController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
@ApiOperation(value = "数据脱敏")
@PostMapping("/desensitize")
public ResResult<MaskingVo> encrypt(@RequestBody MaskingVo maskingVo) {
if (!IdcardUtil.isValidCard(maskingVo.getIdCard())) {
return ResResult.failed().setMsgValue("身份证格式出错");
}
if (StringUtils.isEmpty(maskingVo.getUserName())) {
return ResResult.failed().setMsgValue("用户姓名不能为空");
}
MaskingVo vo = new MaskingVo();
vo.setUserName(ESAPI.encoder().encodeForDN(CommonUtil.nameDesensitization(maskingVo.getUserName())));
vo.setIdCard(ESAPI.encoder().encodeForDN(CommonUtil.idCardEncrypt(maskingVo.getIdCard())));
return ResResult.success().goRecord(vo);
}
}
......@@ -25,10 +25,15 @@ import iot.sixiang.license.service.AlarmReadService;
import iot.sixiang.license.service.AlarmService;
import iot.sixiang.license.service.MonitorService;
import iot.sixiang.license.service.ServerService;
import iot.sixiang.license.xss.BeanCopyUtil;
import iot.sixiang.license.xss.XssUtil;
import lombok.extern.slf4j.Slf4j;
import org.owasp.esapi.ESAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -52,12 +57,17 @@ public class OperateController {
@Autowired
private ForwardManager forwardManager;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
@ApiOperation(value = "服务接口", notes = "用于获取服务列表")
@GetMapping("monitor/server")
@MyLog(title = "获取服务列表", businessType = BusinessType.SELECT)
public ResResult<SamMonitor> getDeviceTypes() {
List<SamMonitor> records = operateManager.getSamMonitorList();
return ResResult.success().record(records);
return ResResult.success().goRecord(records);
}
......@@ -71,10 +81,10 @@ public class OperateController {
@ApiOperation(value = "获取并发量接口", notes = "用于获取并发量")
@GetMapping("monitor/qps")
@MyLog(title = "获取并发量", optParam = "#{type}", businessType = BusinessType.SELECT)
@ApiImplicitParam(name = "type",value = "类型:0:今天 1:昨天 2:七天前 3:三十天前",required = true, dataType = "int")
@ApiImplicitParam(name = "type", value = "类型:0:今天 1:昨天 2:七天前 3:三十天前", required = true, dataType = "int")
public ResResult<QpsVo> getQps(@RequestParam("type") int type) {
HashMap<String, List<Integer>> monitorList = monitorService.getMonitorList(type);
return ResResult.success().record(monitorList);
return ResResult.success().goRecord(monitorList);
}
@ApiOperation(value = "获取服务自诊断信息接口", notes = "用于获取服务诊断信息")
......@@ -83,7 +93,7 @@ public class OperateController {
@ApiImplicitParam()
public ResResult<ServerStatusVo> getDiagnosisInfo() {
ServerStatusVo serverStatus = forwardManager.getServerStatus();
return ResResult.success().record(serverStatus);
return ResResult.success().goRecord(serverStatus);
}
......@@ -91,19 +101,20 @@ public class OperateController {
@GetMapping("alarm/list")
@MyLog(title = "获取告警列表", businessType = BusinessType.SELECT)
public ResResult<List<AlarmVo>> getAlarmList() {
String userId = UserUtils.getLoginUserId();
int Id = Integer.valueOf(userId);
List<AlarmVo> alarmList = alarmService.getAlarmList(Id);
return ResResult.success().record(alarmList);
String user = UserUtils.getLoginUserId();
int userI = Integer.valueOf(user);
List<AlarmVo> alarmList = alarmService.getAlarmList(userI);
List<AlarmVo> alarmVos = BeanCopyUtil.copyListProperties(alarmList, AlarmVo::new);
return ResResult.success().goRecord(alarmVos);
}
@ApiOperation(value = "告警已读接口", notes = "将告警信息状态设为已读")
@PostMapping("alarm/read")
@MyLog(title = "将告警信息状态设为已读", businessType = BusinessType.OTHER)
public BaseResult readAlarm(){
String id = UserUtils.getLoginUserId();
int userId = Integer.valueOf(id);
boolean res = alarmReadService.readAlarm(userId);
public BaseResult readAlarm() {
String i = UserUtils.getLoginUserId();
int uI = Integer.valueOf(i);
boolean res = alarmReadService.readAlarm(uI);
if (res) {
return BaseResult.success();
} else {
......@@ -116,35 +127,33 @@ public class OperateController {
@MyLog(title = "统计sam总数", businessType = BusinessType.SELECT)
public ResResult<SamVo> getSamTotalCount() {
Map<String, SamMonitor> samMonitorMap = operateManager.getSamMonitorMap();
Map<String,Integer> map = new HashMap<>();
Map<String, Integer> map = new HashMap<>();
int totalSamCount = 0;
int totalOnlineCount = 0;
for (SamMonitor samMonitor: samMonitorMap.values()) {
for (SamMonitor samMonitor : samMonitorMap.values()) {
totalSamCount += samMonitor.getSamCount();
totalOnlineCount += samMonitor.getOnlineCount();
}
SamVo samVo = new SamVo();
samVo.setTotalOnlineCount(totalOnlineCount);
samVo.setTotalSamCount(totalSamCount);
return ResResult.success().record(samVo);
return ResResult.success().goRecord(samVo);
}
/**
* 添加server
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "添加服务接口", notes = "用于添加服务")
@PostMapping("server/add")
@MyLog(title = "添加服务", optParam = "#{jsonObject}", businessType = BusinessType.INSERT)
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject",properties = {
@DynamicParameter(name = "serverIp",value = "服务Ip",required = true,dataTypeClass = String.class),
@DynamicParameter(name = "port",value = "端口",required = true,dataTypeClass = Integer.class)
}))
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {@DynamicParameter(name = "serverIp", value = "服务Ip", required = true, dataTypeClass = String.class), @DynamicParameter(name = "port", value = "端口", required = true, dataTypeClass = Integer.class)}))
public BaseResult addServer(@RequestBody JSONObject jsonObject) {
String serverIp = jsonObject.getString("serverIp");
int port = jsonObject.getIntValue("port");
boolean res = serverService.addServer(serverIp,port);
boolean res = serverService.addServer(serverIp, port);
if (res) {
return BaseResult.success();
} else {
......@@ -154,6 +163,7 @@ public class OperateController {
/**
* 删除server
*
* @param serverIp
* @return
*/
......@@ -161,6 +171,7 @@ public class OperateController {
@ApiOperation(value = "删除服务接口", notes = "删除服务")
@PostMapping("server/delete")
public BaseResult deleteServer(@RequestParam("serverIp") String serverIp) {
serverIp = XssUtil.checkXSS(serverIp);
boolean res = serverService.deleteServer(serverIp);
if (res) {
return BaseResult.success();
......@@ -171,20 +182,18 @@ public class OperateController {
/**
* 修改server
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "修改服务接口", notes = "修改服务")
@PostMapping("server/update")
@MyLog(title = "修改服务", optParam = "#{serverIp},#{port}", businessType = BusinessType.UPDATE)
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject",properties = {
@DynamicParameter(name = "serverIp",value = "服务Ip",required = true,dataTypeClass = String.class),
@DynamicParameter(name = "port",value = "端口",required = true,dataTypeClass = Integer.class)
}))
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {@DynamicParameter(name = "serverIp", value = "服务Ip", required = true, dataTypeClass = String.class), @DynamicParameter(name = "port", value = "端口", required = true, dataTypeClass = Integer.class)}))
public BaseResult updateServer(@RequestBody JSONObject jsonObject) {
String serverIp = jsonObject.getString("serverIp");
int port = jsonObject.getInteger("port");
boolean res = serverService.updateServer(serverIp,port);
boolean res = serverService.updateServer(serverIp, port);
if (res) {
return BaseResult.success();
} else {
......@@ -195,6 +204,7 @@ public class OperateController {
/**
* 分页查询所有的server
*
* @param pageNo
* @param pageSize
* @return
......@@ -202,13 +212,9 @@ public class OperateController {
@ApiOperation(value = "获取服务列表接口", notes = "用于获取服务列表")
@GetMapping("server/list")
@MyLog(title = "获取服务列表", optParam = "#{pageNo},#{pageSize}", businessType = BusinessType.SELECT)
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo",value = "当前在第几页", required = true,dataType = "int"),
@ApiImplicitParam(name = "pageSize",value = "每页显示多少条", required = true, dataType = "int")
})
public ResResult<List<Server>> getServerList(@RequestParam("pageNo") int pageNo,
@RequestParam("pageSize") int pageSize) {
List<Server> records = serverService.getServerList(pageNo,pageSize);
return ResResult.success().record(records);
@ApiImplicitParams({@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"), @ApiImplicitParam(name = "pageSize", value = "每页显示多少条", required = true, dataType = "int")})
public ResResult<List<Server>> getServerList(@RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize) {
List<Server> records = serverService.getServerList(pageNo, pageSize);
return ResResult.success().goRecord(records);
}
}
......@@ -32,5 +32,4 @@ public class ResourceContrller {
public void downloadWorkHourRecordTemplate(HttpServletResponse response, @RequestParam(value = "userId") int userId) {
resourceManager.downloadDeviceInfoExcle(response, userId);
}
}
......@@ -4,22 +4,18 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.log.BusinessType;
import iot.sixiang.license.log.MyLog;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.PageResult;
import iot.sixiang.license.model.vo.SysOperLogVo;
import iot.sixiang.license.service.SysOperLogService;
import iot.sixiang.license.util.CommonUtil;
import org.apache.commons.lang3.StringUtils;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
/**
......@@ -35,7 +31,6 @@ public class SysOperLogController {
/**
* 分页查询所有的oper_log
*
* @param pageNo
* @param pageSize
* @return
......@@ -44,28 +39,19 @@ public class SysOperLogController {
@GetMapping("operate/list")
@MyLog(title = "获取日志列表", businessType = BusinessType.SELECT)
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "每页显示多少条", required = true, dataType = "int"),
@ApiImplicitParam(name = "startTime", value = "开始时间"),
@ApiImplicitParam(name = "endTime", value = "结束时间")
@ApiImplicitParam(name = "pageNo",value = "当前在第几页", required = true,dataType = "int"),
@ApiImplicitParam(name = "pageSize",value = "每页显示多少条", required = true, dataType = "int")
})
public PageResult<SysOperLog> getOperLogList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo,
@RequestParam(value = "pageSize", defaultValue = "0") int pageSize,
@RequestParam(value = "startTime", required = false, defaultValue = "") String startTime,
@RequestParam(value = "endTime", required = false, defaultValue = "") String endTime) throws ParseException {
if (StringUtils.isEmpty(endTime)) {
endTime = CommonUtil.getDayByNum(1, CommonUtil.dateToString(new Date(), "yyyy-MM-dd"));
} else {
endTime = CommonUtil.getDayByNum(1, endTime);
}
PageInfoModel<SysOperLog> records = sysOperLogService.getOperLogList(pageNo, pageSize, startTime, endTime);
public PageResult<SysOperLogVo> getOperLogList(@RequestParam(value = "pageNo", defaultValue = "0") int pageNo,
@RequestParam(value = "pageSize",defaultValue = "0") int pageSize) {
PageInfoModel<SysOperLogVo> records = sysOperLogService.getOperLogList(pageNo,pageSize);
int total = records.getTotal();
int pages = total / pageSize;//pages为总页数
int mod = total % pageSize;
if (mod != 0) {
pages = pages + 1;
int pages = total/pageSize;//pages为总页数
int mod = total%pageSize;
if(mod!=0){
pages = pages +1;
}
List<SysOperLog> result = records.getResult();
List<SysOperLogVo> result = records.getResult();
return new PageResult(200, "查找成功", pageNo, pages, total, result);
}
}
package iot.sixiang.license.controller;
import com.acc.secret.util.RSAUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
......@@ -9,16 +10,23 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.license.entity.User;
import iot.sixiang.license.jwt.UserUtils;
import iot.sixiang.license.log.BusinessType;
import iot.sixiang.license.log.MyLog;
import iot.sixiang.license.model.BaseResult;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.PageResult;
import iot.sixiang.license.model.dto.UpdateNotifyDTO;
import iot.sixiang.license.model.vo.UserUpdatePwdVo;
import iot.sixiang.license.model.vo.UserVo;
import iot.sixiang.license.service.UserService;
import iot.sixiang.license.util.CommonUtil;
import iot.sixiang.license.xss.XssUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
......@@ -38,6 +46,20 @@ public class UserController {
@Autowired
private UserService userService;
@Value("${rsa.private_key}")
private String PRIVATE_KRY;
@Value("${other.error_count.change_pwd}")
private Integer changePwdMaxErrCount;
@Value("${spring.mail.to}")
private String account;
private static final String OPERATION_CHANGE = "change";
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(new String[]{"adminCome"});
}
/**
* 添加user
......@@ -74,6 +96,8 @@ public class UserController {
@PostMapping("delete")
@MyLog(title = "删除用户", optParam = "#{userId}", businessType = BusinessType.DELETE)
public BaseResult deleteUser(@RequestParam("userId") int userId) {
userId = Integer.valueOf(XssUtil.checkXSS(String.valueOf(userId)));
boolean res = userService.deleteUser(userId);
if (res) {
return BaseResult.success();
......@@ -82,28 +106,94 @@ public class UserController {
}
}
/**
* 修改user
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "用户修改接口", notes = "修改用户")
@PostMapping("update")
@MyLog(title = "修改用户", optParam = "#{userId},#{password}", businessType = BusinessType.UPDATE)
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "userId", value = "用户Id", required = true, dataTypeClass = Integer.class),
@DynamicParameter(name = "password", value = "密码", required = true, dataTypeClass = String.class)
}))
public BaseResult updateUser(@RequestBody JSONObject jsonObject) {
int userId = jsonObject.getInteger("userId");
String password = jsonObject.getString("password");
boolean res = userService.updateUser(userId, password);
if (res) {
return BaseResult.success();
///**
// * 修改user
// *
// * @param jsonObject
// * @return
// */
//@ApiOperation(value = "用户修改接口", notes = "修改用户")
//@PostMapping("update")
//@MyLog(title = "修改用户", optParam = "#{userId},#{password}", businessType = BusinessType.UPDATE)
//@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
// @DynamicParameter(name = "userId", value = "用户Id", required = true, dataTypeClass = Integer.class),
// @DynamicParameter(name = "password", value = "密码", required = true, dataTypeClass = String.class)
//}))
//public BaseResult updateUser(@RequestBody JSONObject jsonObject) {
// int userId = jsonObject.getInteger("userId");
// String password = jsonObject.getString("password");
// boolean res = userService.updateUser(userId, password);
// if (res) {
// return BaseResult.success();
// } else {
// return BaseResult.failed();
// }
//}
@ApiOperation(value = "用户修改密码", notes = "修改密码")
@PostMapping("update_pwd")
@MyLog(title = "修改密码", businessType = BusinessType.UPDATE)
public BaseResult updatePwd(@RequestBody UserUpdatePwdVo userUpdatePwdVo) {
String errCntTimeMap = UserUtils.getErrCntTimeMap(account + OPERATION_CHANGE);
if (!StringUtils.isEmpty(errCntTimeMap)) {
if (errCntTimeMap.equals(CommonUtil.getCurDateStr())) {
return BaseResult.failed().setMsgValue("今日尝试修改密码次数已达" + changePwdMaxErrCount + "次,请明日再试");
} else {
UserUtils.removeErrCntTimeMap(account + OPERATION_CHANGE);
UserUtils.removeErrCnt(account + OPERATION_CHANGE);
}
}
String oldPassWord = userUpdatePwdVo.getOldPassWord();
String newPassWord = userUpdatePwdVo.getNewPassWord();
String userId = UserUtils.getLoginUserId();
User user;
if (!StringUtils.isEmpty(userId)) {
user = userService.getUserById(Integer.parseInt(userId));
} else {
return BaseResult.failed();
}
oldPassWord = RSAUtil.getDecryptString(oldPassWord, PRIVATE_KRY);
newPassWord = RSAUtil.getDecryptString(newPassWord, PRIVATE_KRY);
Integer errCnt = UserUtils.getErrCnt(account + OPERATION_CHANGE);
if (errCnt == null) {
errCnt = 0;
}
if (oldPassWord.equals(user.getPassword())) {
if (newPassWord.length() < 8) {
computeChangePwdErrCnt(errCnt);
return BaseResult.failed().setMsgValue("密码不得小于8位");
}
if (CommonUtil.verifyPasswordContainAccount(newPassWord, user.getUserName())) {
computeChangePwdErrCnt(errCnt);
return BaseResult.failed().setMsgValue("密码中不得包含用户名的完整字符串、大小写变位或形似变换的字符串");
}
if (CommonUtil.isKeyBoardContinuousChar(newPassWord)) {
computeChangePwdErrCnt(errCnt);
return BaseResult.failed().setMsgValue("密码不得包含键盘连续字符4个及以上");
}
if (!CommonUtil.checkPassword(newPassWord)) {
computeChangePwdErrCnt(errCnt);
return BaseResult.failed().setMsgValue("至少由大写字母、小写字母、数字与特殊符号等4类中3类混合");
}
user.setPassword(newPassWord);
boolean b = userService.updateUser(user);
if (b) {
return BaseResult.success().setMsgValue("密码修改成功");
} else {
return BaseResult.failed().setMsgValue("密码修改失败");
}
} else {
computeChangePwdErrCnt(errCnt);
return BaseResult.failed().setMsgValue("原密码出错");
}
}
private void computeChangePwdErrCnt(int errCnt) {
if (errCnt < changePwdMaxErrCount - 1) {
UserUtils.setErrCnt(account + OPERATION_CHANGE, errCnt + 1);
} else {
UserUtils.setErrCntTimeMap(account + OPERATION_CHANGE, CommonUtil.getCurDateStr());
}
}
......@@ -127,6 +217,8 @@ public class UserController {
@RequestParam(value = "pageSize", defaultValue = "0") int pageSize,
@RequestParam(value = "userName", required = false) String userName,
@RequestParam(value = "company", required = false) String company) {
userName = XssUtil.checkXSS(userName);
company = XssUtil.checkXSS(company);
PageInfoModel<UserVo> records = userService.getUserList(pageNo, pageSize, userName, company);
int total = records.getTotal();
int pages = total / pageSize;//pages为总页数
......@@ -135,13 +227,11 @@ public class UserController {
pages = pages + 1;
}
List<UserVo> result = records.getResult();
return new PageResult(200, "查找成功", pageNo, pages, total, result);
String str = "uBtWZTiPMYkQLsp7rNly3RUIXKGqFbjnSg56H8ve49AC0mfO";
for (UserVo u : result) {
u.setPassword(DigestUtils.md5DigestAsHex((str + u.getPassword()).getBytes()));
}
@ApiOperation(value = "修改通知人接口", notes = "修改通知人邮箱")
@PostMapping("update_notify")
public BaseResult updateNotify(@RequestBody UpdateNotifyDTO updateNotifyDTO) {
return userService.updateNotify(updateNotifyDTO);
return new PageResult(200, "查找成功", pageNo, pages, total, result);
}
}
package iot.sixiang.license.device;
import iot.sixiang.license.net.TcpServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* Title: AsyncTcpServer
* Description: TODO
*
* @author tianlai3
* @date 2022-07-16 20:30:51
*/
@Component
@Slf4j
public class AsyncTcpServer {
@Async("taskExecutor")
public void start(int port, DeviceChannelInitializer channelInitializer) {
TcpServer server = new TcpServer(port, channelInitializer);
server.start();
}
}
......@@ -22,12 +22,10 @@ public class DeviceChannelInitializer extends BaseChannelInitializer {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 服务端心跳检测
ch.pipeline().addLast(new IdleStateHandler(3, 0, 0, TimeUnit.SECONDS));
ch.pipeline().addLast("decoder", new DeviceDecoder());
ch.pipeline().addLast("encoder", new DeviceEncoder());
ch.pipeline().addLast(workGroup, "handler", handler);
}
}
......@@ -5,7 +5,6 @@ import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.SessionContext;
import iot.sixiang.license.model.vo.DeviceDetailVo;
import iot.sixiang.license.model.vo.DeviceVo;
import iot.sixiang.license.net.TcpServer;
import iot.sixiang.license.service.DeviceService;
import iot.sixiang.license.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
......@@ -25,17 +24,19 @@ import java.util.Map;
public class DeviceManager {
private Map<String, SessionContext> sessionContexts = null;
private DeviceChannelInitializer channelInitializer;
private TcpServer server = null;
// private TcpServer server = null;
private int port = 18889;
private Map<String, DeviceVo> allDevice = null;
@Autowired
private DeviceService deviceService;
@Autowired
private DeviceServerHandler handler;
@Autowired
private AsyncTcpServer asyncTcpServer;
public DeviceManager() {
sessionContexts = new HashMap<String, SessionContext>();
allDevice = new HashMap<String, DeviceVo>();
sessionContexts = new HashMap<>();
allDevice = new HashMap<>();
}
@PostConstruct
......@@ -44,11 +45,11 @@ public class DeviceManager {
initDevices();
}
private void startTcpService() {
sessionContexts = new HashMap<String, SessionContext>();
sessionContexts = new HashMap<>();
channelInitializer = new DeviceChannelInitializer(handler);
server = new TcpServer(port, channelInitializer);
server.start();
asyncTcpServer.start(port, channelInitializer);
}
public void initDevices() {
......@@ -134,7 +135,6 @@ public class DeviceManager {
}
public boolean changeSessionOffline(String channelId) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
......@@ -156,7 +156,6 @@ public class DeviceManager {
PageInfoModel<DeviceDetailVo> detailVoPageInfoModel = new PageInfoModel<>();
List<DeviceDetailVo> detailVos = new ArrayList<>();
for (DeviceVo vo : deviceVos) {
DeviceDetailVo detailVo = new DeviceDetailVo();
detailVo.setDeviceId(vo.getDeviceId());
detailVo.setAppName(vo.getAppName());
......@@ -173,8 +172,6 @@ public class DeviceManager {
detailVo.setCurStatus(status);
detailVo.setOnline(online);
detailVo.setOffline(offline);
}
detailVos.add(detailVo);
}
......
......@@ -14,11 +14,11 @@ import iot.sixiang.license.event.DeviceClientInactiveEvent;
import iot.sixiang.license.event.DeviceClientLicenseEvent;
import iot.sixiang.license.event.EventPublisher;
import iot.sixiang.license.event.ForwardClientRequestEvent;
import iot.sixiang.license.idreader.Safety;
import iot.sixiang.license.model.SessionContext;
import iot.sixiang.license.model.dto.ReportErrorMsgDTO;
import iot.sixiang.license.service.PmsUseService;
import iot.sixiang.license.service.TerminalDeviceService;
import iot.sixiang.license.third_lib.LibHelper;
import iot.sixiang.license.util.CommonUtil;
import iot.sixiang.license.util.HexUtil;
import iot.sixiang.license.util.SpringUtil;
......@@ -37,8 +37,6 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Autowired
EventPublisher eventPublisher;
@Autowired
Safety safety;
@Resource
private PmsUseService pmsUseService;
@Resource
......@@ -87,8 +85,9 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.info("设备服务器,channelRegistered:{}", ctx.channel().id().asLongText());
log.debug("设备服务器,channelRegistered:{}", ctx.channel().id().asLongText());
}
@Override
......@@ -125,7 +124,8 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
private boolean handleCheckAuth(SocketChannel channel, String remoteIp, int remotePort, DeviceProtocol protocol) {
// 正式代码要放开
byte[] bytes = safety.decodeExtendedPayload(protocol.getContent(), 0, protocol.getContent().length);
LibHelper libHelper = SpringUtil.getBean(LibHelper.class);
byte[] bytes = libHelper.decodeExtendedPayload(protocol.getContent(), 0, protocol.getContent().length);
if (bytes == null) {
return false;
}
......
......@@ -35,7 +35,7 @@ public class SysOperLog implements Serializable {
@ApiModelProperty("参数")
private String optParam;
@ApiModelProperty("业务类型(0其它 1新增 2修改 3删除)")
@ApiModelProperty("业务类型(0其它 1查找 2新增 3修改 4删除)")
private Integer businessType;
@ApiModelProperty("路径名称")
......@@ -49,6 +49,4 @@ public class SysOperLog implements Serializable {
@ApiModelProperty("操作时间")
private Date operTime;
}
......@@ -18,7 +18,6 @@ public class CreateForwardClientEventHandler {
@Autowired
BalanceManager balanceManager;
public CreateForwardClientEventHandler() {
}
......
package iot.sixiang.license.event;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class EventPublisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
......
......@@ -22,7 +22,6 @@ public class ForwardClientRequestEventHandler {
public ForwardClientRequestEventHandler() {
}
@EventListener
......
......@@ -58,7 +58,7 @@ public class OperateSAMStatusResponseEventHandler {
samMonitor.setOnlineCount(onlineCount);
samMonitor.setSamCount(samCount);
operateManager.putSamMonitorMap(serverIp, samMonitor);
if (onlineCount / samCount > 0.7) {
if ((float)onlineCount / samCount > 0.7) {
int typeId = 3;
String title = "SAM不足";
String content = "当前在线客户端已超过70%";
......
package iot.sixiang.license.forward;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import iot.sixiang.license.device.DeviceManager;
import iot.sixiang.license.net.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@Component
......@@ -13,6 +19,7 @@ import javax.annotation.Resource;
public class ForwardClient {
private TcpClient client = null;
private ForwardChannelInitializer channelInitializer;
private Bootstrap bootstrap;
@Autowired
ForwardClientHandler handler;
......@@ -22,6 +29,22 @@ public class ForwardClient {
public ForwardClient() {
}
@PostConstruct
public void init() {
channelInitializer = new ForwardChannelInitializer(handler);
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
try {
bootstrap
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.group(eventLoopGroup)
.handler(channelInitializer);
} catch (IllegalStateException ex) {
log.error(ex.getMessage());
}
}
public void startTcp(String host, int port, String sn) {
log.debug("桥接客户端,开始连接桥接服务:{},{},{}", host, port, sn);
ForwardConnectionListener listener = new ForwardConnectionListener();
......@@ -31,7 +54,7 @@ public class ForwardClient {
listener.setDeviceManager(this.deviceManager);
channelInitializer = new ForwardChannelInitializer(handler);
client = new TcpClient(host, port, channelInitializer, listener);
client = new TcpClient(host, port, channelInitializer, listener, bootstrap);
client.start();
}
}
......@@ -32,9 +32,6 @@ public class ForwardClientHandler extends SimpleChannelInboundHandler<Object> {
// 中转客户端收到消息后,将消息原封不动的发送给设备客户端
log.info("read message...");
SocketChannel channel = (SocketChannel) ctx.channel();
//InetSocketAddress socketAddr = (InetSocketAddress) ctx.channel().remoteAddress();
//String serverIp = socketAddr.getHostString();
//int serverPort = socketAddr.getPort();
DeviceProtocol protocol = (DeviceProtocol) msg;
String channelId = channel.id().asLongText();
......
......@@ -17,7 +17,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody //为了返回数据
public BaseResult error(Exception e){
log.error("出现自定义异常,{}", e.getMessage());
log.error("出现自定义异常", e);
return BaseResult.serverException();
}
......@@ -25,7 +25,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(IotLicenseException.class)
@ResponseBody//为了返回数据
public BaseResult error(IotLicenseException e){
log.error("出现自定义异常,{}", e.getMsg());
return BaseResult.failed().msg(e.getMsg()).code(e.getCode());
log.error("出现自定义异常,{}" + e.getMsg());
return BaseResult.failed().setMsgValue(e.getMsg()).setCodeValue(e.getCode());
}
}
package iot.sixiang.license.idreader;
import iot.sixiang.license.util.CommonUtil;
import org.springframework.stereotype.Component;
@Component
public class Safety {
static {
System.load(CommonUtil.getLibFilePathByFileName("IdReaderSafetyLib"));
}
public native byte[] decodeExtendedPayload(byte[] data, int offset, int length);
}
\ No newline at end of file
......@@ -29,7 +29,6 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
response.setHeader("Set-Cookie","HttpOnly");
return true;
}
}
\ No newline at end of file
......@@ -2,31 +2,36 @@ package iot.sixiang.license.jwt;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import iot.sixiang.license.xss.XssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
@Slf4j
@WebFilter(filterName = "jwtFilter", urlPatterns = "/*")
public class JwtFilter implements Filter {
private static final String url1 = "/login";
private static final String url2 = "/resource";
private static final String url2 = "/send_code";
private static final String url3 = "/doc.html";
private static final String url4 = "/v2/api-docs";
private static final String url7 = "/swagger-resources";
private static final String url8 = "/webjars/";
private static final String url9 = "/log/get";
private static final String url9 = "/check_code";
private static final String url10 = "/reset_pwd";
private static final String url11 = "/get_token";
private static final String url12 = "/report_error_msg";
private static final String url13 = "/bind";
......@@ -41,10 +46,13 @@ public class JwtFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Set-Cookie", "cookiename=cookievalue; path=/; Domain=domainvaule; Max-age=seconds; HttpOnly");
response.setContentType("text/html; charset=utf-8");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
filterChain.doFilter(request, response);
if (!"GET".equals(request.getMethod()) && !"POST".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(new String("不安全的请求".getBytes(), StandardCharsets.UTF_8).getBytes());
outputStream.flush();
return;
}
......@@ -52,8 +60,9 @@ public class JwtFilter implements Filter {
boolean check = true;
String uri = request.getRequestURI();
if (uri.contains(url1) || uri.contains(url2) || uri.contains(url3) || uri.contains(url4) || uri.contains(url7) || uri.contains(url8) || uri.contains(url9) || uri.contains(url11)) {
if (uri.contains(url1) || uri.contains(url2) || uri.contains(url3) || uri.contains(url4) || uri.contains(url7) || uri.contains(url8) || uri.contains(url9) || uri.contains(url10) || uri.contains(url11)) {
if (uri.contains(url1) || uri.contains(url2)) {
uri = XssUtil.checkXSS(uri);
UserUtils.setUri(uri);
}
check = false;
......@@ -63,21 +72,21 @@ public class JwtFilter implements Filter {
return;
}
if (token == null) {
if (StringUtils.isEmpty(token)) {
request.setAttribute("msg", "认证信息不能为空");
request.getRequestDispatcher("/fail").forward(request, response);
request.getRequestDispatcher("/iot_license/fail").forward(request, response);
return;
} else {
DecodedJWT jwt = JwtUtil.verifyToken(token);
if (jwt == null) {
request.setAttribute("msg", "认证信息非法");
request.getRequestDispatcher("/fail").forward(request, response);
request.getRequestDispatcher("/iot_license/fail").forward(request, response);
return;
} else {
Map<String, Claim> userData = jwt.getClaims();
if (userData == null) {
request.setAttribute("msg", "认证信息非法");
request.getRequestDispatcher("/fail").forward(request, response);
request.getRequestDispatcher("/iot_license/fail").forward(request, response);
return;
}
// 终端设备放行
......@@ -87,12 +96,25 @@ public class JwtFilter implements Filter {
}
String userId = userData.get("userId").asString();
String userName = userData.get("userName").asString();
String password = userData.get("password").asString();
String password = "";
if (!token.equals(UserUtils.getToken(userId))) {
request.setAttribute("msg", "账户已在别处登录,请重新登录");
request.getRequestDispatcher("/iot_license/fail").forward(request, response);
return;
}
LoginUser loginUser = new LoginUser(userId, userName, password);
Date curDate = new Date();
Date tokenExp = UserUtils.getTokenExp(userId);
if (token.equals(UserUtils.getToken(userId)) && curDate.before(tokenExp)) {
UserUtils.setLoginUser(loginUser);
UserUtils.setUri(uri);
filterChain.doFilter(request, response);
} else {
UserUtils.removeToken(userId);
UserUtils.removeTokenExp(userId);
request.setAttribute("msg", "token已过期");
request.getRequestDispatcher("/iot_license/fail").forward(request, response);
}
}
}
}
......
......@@ -3,6 +3,7 @@ package iot.sixiang.license.jwt;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
......@@ -15,7 +16,7 @@ public class JwtUtil {
/**
* 秘钥
*/
private static final String SECRET = "my_secret";
private static final String SECRET = "zIG4UAymevO6CYkDqRJuXnLWdb8c9a7xNlf51irhsSZjwtgQ";
/**
* 过期时间
......@@ -38,8 +39,8 @@ public class JwtUtil {
//可以把数据存在claim中
.withClaim("userId", user.getUserId())
.withClaim("userName", user.getUserName())
.withClaim("password", user.getPassword())
.withExpiresAt(expireDate) //超时设置,设置过期的日期
// .withClaim("password", user.getPassword())
// .withExpiresAt(expireDate) //超时设置,设置过期的日期
.withIssuedAt(new Date()) //签发时间
.sign(Algorithm.HMAC256(SECRET)); //SECRET加密
return token;
......@@ -69,10 +70,16 @@ public class JwtUtil {
DecodedJWT jwt = null;
try {
jwt = verifier.verify(token);
} catch ( RuntimeException e) {
} catch (JWTVerificationException e) {
log.error(e.getMessage());
log.error("解析编码异常");
}
return jwt;
}
public static Date getTokenExp() {
//过期时间
Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
return expireDate;
}
}
package iot.sixiang.license.jwt;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 存储/获取当前线程的用户信息工具类
*/
public abstract class UserUtils {
//线程变量,存放user实体类信息,即使是静态的与其他线程也是隔离的
static Map<String, String> tokenMap = new HashMap<>();
static Map<String, Date> tokenExpTimeMap = new HashMap<>();
static Map<String, Integer> errCntMap = new HashMap<>();
static Map<String, String> errCntTimeMap = new HashMap<>();
static Map<String, String> emailCodeMap = new HashMap<>();
static Map<String, Date> emailCodeExpTimeMap = new HashMap<>();
static Map<String, Date> countFreezeDateMap = new HashMap<>();
static Map<String, Integer> codeErrCntMap = new HashMap<>();
static Map<String, String> codeFreezeTimeMap = new HashMap<>();
/**
* 线程变量,存放user实体类信息,即使是静态的也与其他线程也是隔离的
*/
private static ThreadLocal<LoginUser> userThreadLocal = new ThreadLocal<>();
//线程变量,存放uri,即使是静态的与其他线程也是隔离的
private static ThreadLocal<String> uriThreadLocal = new ThreadLocal<>();
//从当前线程变量中获取用户信息
public static LoginUser getLoginUser() {
LoginUser user = userThreadLocal.get();
return user;
......@@ -31,32 +46,137 @@ public abstract class UserUtils {
return null;
}
//为当前的线程变量赋值上用户信息
public static void setLoginUser(LoginUser user) {
userThreadLocal.set(user);
}
//清除userThreadLocal线程变量
public static void removeUser() {
userThreadLocal.remove();
}
//为当前的线程变量赋值上uri信息
public static void setUri(String uri) {
uriThreadLocal.set(uri);
}
/**
* 获取当前访问方法的uri
* @return
*/
public static String getUri() {
String uri = uriThreadLocal.get();
return uri;
}
//清除uriThreadLocal线程变量
public static void removeUri() {
uriThreadLocal.remove();
}
public static void setToken(String uId, String token) {
tokenMap.put(uId, token);
}
public static String getToken(String uId) {
System.out.println("---");
String s = tokenMap.get(uId);
System.out.println(s);
return tokenMap.get(uId);
}
public static void removeToken(String uId) {
tokenMap.remove(uId);
}
public static void setTokenExp(String uId, Date tokenExpTime) {
tokenExpTimeMap.put(uId, tokenExpTime);
}
public static Date getTokenExp(String uId) {
return tokenExpTimeMap.get(uId);
}
public static void removeTokenExp(String uId) {
tokenExpTimeMap.remove(uId);
}
public static void setErrCnt(String uId, Integer count) {
errCntMap.put(uId, count);
}
public static Integer getErrCnt(String uId) {
return errCntMap.get(uId);
}
public static void removeErrCnt(String uId) {
errCntMap.remove(uId);
}
public static void setCountFreezeDate(String uId, Date freezeDate) {
countFreezeDateMap.put(uId, freezeDate);
}
public static Date getCountFreezeDate(String uId) {
return countFreezeDateMap.get(uId);
}
public static void removeCountFreezeDate(String uId) {
countFreezeDateMap.remove(uId);
}
public static void setEmailCode(String email, String code) {
emailCodeMap.put(email, code);
}
public static String getEmailCode(String email) {
return emailCodeMap.get(email);
}
public static void removeEmailCode(String email) {
emailCodeMap.remove(email);
}
public static void setEmailCodeExpTime(String email, Date expTime) {
emailCodeExpTimeMap.put(email, expTime);
}
public static Date getEmailCodeExpTime(String email) {
return emailCodeExpTimeMap.get(email);
}
public static void removeEmailCodeExpTime(String email) {
emailCodeExpTimeMap.remove(email);
}
public static void setCodeErrCntMap(String account, int count) {
codeErrCntMap.put(account, count);
}
public static Integer getCodeErrCntMap(String account) {
return codeErrCntMap.get(account);
}
public static void removeCodeErrCntMap(String account) {
codeErrCntMap.remove(account);
}
public static void setCodeFreezeTimeMap(String account, String timeStr) {
codeFreezeTimeMap.put(account, timeStr);
}
public static String getCodeFreezeTimeMap(String account) {
return codeFreezeTimeMap.get(account);
}
public static void removeCodeFreezeTimeMap(String account) {
codeFreezeTimeMap.remove(account);
}
public static void setErrCntTimeMap(String account, String timeStr) {
errCntTimeMap.put(account, timeStr);
}
public static String getErrCntTimeMap(String account) {
return errCntTimeMap.get(account);
}
public static void removeErrCntTimeMap(String account) {
errCntTimeMap.remove(account);
}
}
......@@ -2,6 +2,7 @@ package iot.sixiang.license.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.model.vo.SysOperLogVo;
import java.util.Date;
import java.util.List;
......@@ -18,5 +19,5 @@ public interface SysOperLogMapper extends BaseMapper<SysOperLog> {
boolean addOperlog(String title, Integer businessType, String uri, Integer status, String optParam, String errorMsg, Date operTime);
List<SysOperLog> getOperLogList(String startTime, String endTime);
List<SysOperLogVo> getOperLogList();
}
......@@ -26,4 +26,6 @@ public interface UserMapper extends BaseMapper<User> {
List<UserVo> getUserList( String userName, String company);
User getUserByUserName(String userName);
User getUserById(int userId);
}
......@@ -69,13 +69,13 @@ public class BaseResult {
}
public BaseResult code(long code) {
public BaseResult setCodeValue(long code) {
this.code = code;
return this;
}
public BaseResult msg(String message) {
public BaseResult setMsgValue(String message) {
this.msg = message;
return this;
}
......
......@@ -30,60 +30,64 @@ public class ResResult<T> {
/**
* code = 200
* msg = 操作成功
*
* @return
*/
public static ResResult success() {
return new ResResult(ResultCode.SUCCESS.getCode(),ResultCode.SUCCESS.getMsg());
return new ResResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
/**
* code = 400
* msg = 服务异常
*
* @return
*/
public static ResResult serverException() {
return new ResResult(ResultCode.SERVER_EXCEPTION.getCode(),ResultCode.SERVER_EXCEPTION.getMsg());
return new ResResult(ResultCode.SERVER_EXCEPTION.getCode(), ResultCode.SERVER_EXCEPTION.getMsg());
}
/**
* code = 401
* msg = 暂未登录或token已经过期
*
* @return
*/
public static ResResult unauthorized() {
return new ResResult(ResultCode.UNAUTHORIZED.getCode(),ResultCode.UNAUTHORIZED.getMsg());
return new ResResult(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMsg());
}
/**
* code = 402
* msg = 参数校验失败
*
* @return
*/
public static ResResult validate_failed() {
return new ResResult(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
return new ResResult(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
/**
* code = 403
* msg = 操作失败(数据库增删改查等失败)
*
* @return
*/
public static ResResult failed() {
return new ResResult(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMsg());
return new ResResult(ResultCode.FAILED.getCode(), ResultCode.FAILED.getMsg());
}
public ResResult code(long code) {
public ResResult setCodeValue(long code) {
this.code = code;
return this;
}
public ResResult msg(String message) {
public ResResult setMsgValue(String message) {
this.msg = message;
return this;
}
public ResResult record(T data){
public ResResult goRecord(T data) {
this.record = data;
return this;
}
......
package iot.sixiang.license.model.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33
* Date 2022/9/23 17:46
* Description
*/
@Data
public class CheckCodeDto {
@ApiModelProperty("验证码")
private String code;
}
package iot.sixiang.license.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Title: EncryptVo
* Description: TODO
*
* @author tianlai3
* @date 2022-07-13 01:10:10
*/
@Data
public class EncryptVo {
@ApiModelProperty(value = "数据")
private String message;
}
package iot.sixiang.license.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* Created by m33
* Date 2022/9/8 10:45
* Description
*/
@Data
public class LoginReqVo {
@ApiModelProperty("用户名")
private String userName;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("验证码")
private String code;
}
......@@ -3,6 +3,8 @@ package iot.sixiang.license.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* Created by m33 on 2022/6/14 18:51
*/
......@@ -11,4 +13,7 @@ public class LoginVo {
@ApiModelProperty("token")
private String authorization;
@ApiModelProperty("更新时间")
private Date updateTime;
}
package iot.sixiang.license.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Title: MaskingVo
* Description: TODO
*
* @author tianlai3
* @date 2022-07-13 01:42:04
*/
@Data
public class MaskingVo {
@ApiModelProperty(value = "用户姓名")
private String userName;
@ApiModelProperty(value = "身份证号")
private String idCard;
}
package iot.sixiang.license.model.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* Created by m33
* Date 2022/9/7 14:52
* Description
*/
@Data
public class SysOperLogVo {
@ApiModelProperty("主键Id")
private Integer id;
@ApiModelProperty("模块标题")
private String title;
@ApiModelProperty("业务类型(0其它 1查找 2新增 3修改 4删除)")
private Integer businessType;
@ApiModelProperty("路径名称")
private String uri;
@ApiModelProperty("操作状态(0正常 1异常)")
private Integer status;
@ApiModelProperty("错误消息")
private String errorMsg;
@ApiModelProperty("操作时间")
private Date operTime;
}
package iot.sixiang.license.model.vo;
import lombok.Data;
/**
* Created by m33
* Date 2022/9/23 18:32
* Description
*/
@Data
public class UserResetPwdVo {
private String password;
}
package iot.sixiang.license.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33
* Date 2022/9/7 15:06
* Description
*/
@Data
public class UserUpdatePwdVo {
@ApiModelProperty(value = "旧密码")
private String oldPassWord;
@ApiModelProperty(value = "新密码")
private String newPassWord;
}
......@@ -2,10 +2,6 @@ package iot.sixiang.license.net;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
......@@ -14,33 +10,18 @@ public class TcpClient {
private String host;
private BaseChannelInitializer channelInitializer;
private BaseConnectionListener connectionListener;
private Bootstrap bootstrap;
public TcpClient(String host, int port, BaseChannelInitializer channelInitializer, BaseConnectionListener connectionListener) {
public TcpClient(String host, int port, BaseChannelInitializer channelInitializer, BaseConnectionListener connectionListener, Bootstrap bootstrap) {
this.host = host;
this.port = port;
this.channelInitializer = channelInitializer;
this.connectionListener = connectionListener;
this.bootstrap = bootstrap;
}
public void start() {
Thread thread = new Thread(() -> {
try {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.group(eventLoopGroup)
.remoteAddress(host, port)
.handler(channelInitializer);
ChannelFuture future = bootstrap.connect(host, port);
future.addListener(connectionListener);
} catch (Exception e) {
e.printStackTrace();
log.error("Tcp客户端异常,端口:{}", port);
}
});
thread.start();
}
}
......@@ -10,7 +10,6 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TcpServer {
private int port;
private BaseChannelInitializer channelInitializer;
......@@ -20,13 +19,10 @@ public class TcpServer {
}
public void start() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//创建两个线程组 bossGroup、workerGroup
EventLoopGroup bossGroup = new NioEventLoopGroup(4);
EventLoopGroup workerGroup = new NioEventLoopGroup(4);
log.debug("Tcp服务,开始监听端口:{}", port);
log.info("Tcp服务,开始监听端口:{}", port);
//创建服务端的启动对象,设置参数
ServerBootstrap b = new ServerBootstrap();
//设置两个线程组boosGroup和workerGroup
......@@ -44,15 +40,15 @@ public class TcpServer {
f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
log.error("Tcp服务异常,端口:{}", port);
} finally {
log.debug("Tcp服务,停止退出");
log.info("Tcp服务,停止退出");
if (workerGroup != null) {
workerGroup.shutdownGracefully();
}
if (bossGroup != null) {
bossGroup.shutdownGracefully();
}
}
});
thread.start();
}
}
package iot.sixiang.license.operate;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import iot.sixiang.license.net.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Slf4j
public class OperateClient {
......@@ -12,7 +19,7 @@ public class OperateClient {
private TcpClient client = null;
private OperateChannelInitializer channelInitializer;
private Bootstrap bootstrap;
@Autowired
OperateClientHandler handler;
......@@ -21,13 +28,28 @@ public class OperateClient {
}
@PostConstruct
public void init(){
channelInitializer = new OperateChannelInitializer(handler);
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
try {
bootstrap
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.group(eventLoopGroup)
.handler(channelInitializer);
} catch (IllegalStateException ex) {
log.error(ex.getMessage());
}
}
public void startTcp(String host, int port) {
OperateConnectionListener listener = new OperateConnectionListener();
listener.setHost(host);
listener.setPort(port);
channelInitializer = new OperateChannelInitializer(handler);
client = new TcpClient(host, port, channelInitializer, listener);
client = new TcpClient(host, port, channelInitializer, listener, bootstrap);
client.start();
}
......
......@@ -22,7 +22,7 @@ public class ResourceManager {
@Autowired
ResourceService resourceService;
public void downloadDeviceInfoExcle(HttpServletResponse response, int userId) throws IOException {
public void downloadDeviceInfoExcle(HttpServletResponse response, int userId){
OutputStream os = null;
HSSFWorkbook wb = null;
try {
......@@ -129,13 +129,21 @@ public class ResourceManager {
}
wb.write(os);
} catch (IOException e) {
log.error("Excel表格信息下载异常,{}",e.getMessage());
log.error("Excel表格信息下载异常,{}", e.getMessage());
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
log.error("Excel表格信息下载异常,{}", e.getMessage());
}
}
if (wb != null) {
try {
wb.close();
} catch (IOException e) {
log.error("Excel表格信息下载异常,{}", e.getMessage());
}
}
}
}
......
......@@ -3,6 +3,7 @@ package iot.sixiang.license.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.vo.SysOperLogVo;
import java.util.Date;
......@@ -17,5 +18,5 @@ import java.util.Date;
public interface SysOperLogService extends IService<SysOperLog> {
boolean addOperlog(String title, Integer businessType, String uri, Integer status, String optParam, String errorMsg, Date operTime);
PageInfoModel<SysOperLog> getOperLogList(int pageNo, int pageSize, String startTime, String endTime);
PageInfoModel<SysOperLogVo> getOperLogList(int pageNo, int pageSize);
}
package iot.sixiang.license.service;
import iot.sixiang.license.model.BaseResult;
import iot.sixiang.license.entity.User;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.dto.UpdateNotifyDTO;
import iot.sixiang.license.model.vo.UserVo;
/**
......@@ -13,15 +12,17 @@ import iot.sixiang.license.model.vo.UserVo;
* @author m33
* @since 2022-06-06
*/
public interface UserService{
public interface UserService {
boolean deleteUser(int userIdVo);
boolean addUser(String userName, String company, String password);
boolean updateUser(int userId, String password);
boolean updateUser(User user);
PageInfoModel<UserVo> getUserList(int pageNo, int pageSize, String userName, String company);
BaseResult updateNotify(UpdateNotifyDTO updateNotifyDTO);
User getUserById(int userId);
User getUserByName(String root);
}
......@@ -8,9 +8,14 @@ import iot.sixiang.license.mapper.AlarmMapper;
import iot.sixiang.license.mapper.AlarmReadMapper;
import iot.sixiang.license.model.vo.AlarmVo;
import iot.sixiang.license.service.AlarmReadService;
import iot.sixiang.license.util.CommonUtil;
import iot.sixiang.license.xss.XssUtil;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
......@@ -29,11 +34,13 @@ public class AlarmReadServiceImpl extends ServiceImpl<AlarmReadMapper, AlarmRead
@Resource
AlarmReadMapper alarmReadMapper;
@Override
public boolean readAlarm(int userId) {
if (userId == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
userId = Integer.valueOf(XssUtil.checkXSS(String.valueOf(userId)));
List<AlarmVo> alarmList = alarmMapper.getAlarmList(userId);
for (AlarmVo alarm: alarmList) {
if (alarm.getReadFlag() == 0) {
......@@ -41,6 +48,12 @@ public class AlarmReadServiceImpl extends ServiceImpl<AlarmReadMapper, AlarmRead
int typeId = alarm.getTypeId();
String title = alarm.getTitle();
String content = alarm.getContent();
alarmId = Integer.valueOf(XssUtil.checkXSS(String.valueOf(alarmId)));
typeId = Integer.valueOf(XssUtil.checkXSS(String.valueOf(typeId)));
title = XssUtil.checkXSS(title);
content = XssUtil.checkXSS(content);
boolean res = alarmReadMapper.readAlarm(alarmId, typeId, title, content, userId);
if (!res) {
return false;
......
......@@ -7,6 +7,8 @@ import iot.sixiang.license.handler.IotLicenseException;
import iot.sixiang.license.mapper.AlarmMapper;
import iot.sixiang.license.model.vo.AlarmVo;
import iot.sixiang.license.service.AlarmService;
import iot.sixiang.license.util.CommonUtil;
import org.owasp.esapi.ESAPI;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
......@@ -25,12 +27,17 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
}
@Override
public List<AlarmVo> getAlarmList(int userId) {
if (userId == 0) {
public List<AlarmVo> getAlarmList(int uI) {
if (uI == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
List<AlarmVo> alarmVos = alarmMapper.getAlarmList(userId);
List<AlarmVo> alarmVos = alarmMapper.getAlarmList(uI);
alarmVos = alarmVos.stream().sorted(Comparator.comparing(AlarmVo::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
if (alarmVos != null && !alarmVos.isEmpty()) {
for (AlarmVo alarmVo : alarmVos) {
alarmVo.setContent(ESAPI.encoder().encodeForDN(alarmVo.getContent()));
}
}
return alarmVos;
}
}
......@@ -138,7 +138,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
queryWrapper.eq(Device::getSnBind, snBind).last("limit 1");
Device device = deviceMapper.selectOne(queryWrapper);
if (device != null) {
return ResResult.success().record(device.getSn());
return ResResult.success().goRecord(device.getSn());
} else {
return new ResResult(405, "未绑定");
}
......@@ -156,7 +156,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
if (deviceId.equals(device.getDeviceId())) {
return BaseResult.success();
} else {
return BaseResult.failed().msg("设备sn已被绑定");
return BaseResult.failed().setMsgValue("设备sn已被绑定");
}
}
LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
......@@ -164,10 +164,10 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
Device tempDevice = deviceMapper.selectOne(wrapper);
if (tempDevice != null) {
if (!StringUtils.isEmpty(tempDevice.getSnBind())) {
return BaseResult.failed().msg("设备已绑定sn");
return BaseResult.failed().setMsgValue("设备已绑定sn");
}
} else {
return BaseResult.failed().msg("请输入正确的id");
return BaseResult.failed().setMsgValue("请输入正确的id");
}
tempDevice.setSn(sn);
tempDevice.setSnBind(snBind);
......
......@@ -6,12 +6,13 @@ import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.handler.IotLicenseException;
import iot.sixiang.license.mapper.SysOperLogMapper;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.vo.SysOperLogVo;
import iot.sixiang.license.service.SysOperLogService;
import iot.sixiang.license.xss.XssUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
......@@ -32,23 +33,29 @@ public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOper
@Override
public boolean addOperlog(String title, Integer businessType, String uri, Integer status, String optParam, String errorMsg, Date operTime) {
title = XssUtil.checkXSS(title);
businessType = Integer.valueOf(XssUtil.checkXSS(String.valueOf(businessType)));
uri = XssUtil.checkXSS(uri);
status = Integer.valueOf(XssUtil.checkXSS(String.valueOf(status)));
optParam = XssUtil.checkXSS(optParam);
errorMsg = XssUtil.checkXSS(errorMsg);
// operTime = XssUtil.checkXSS(operTime);
return sysOperLogMapper.addOperlog(title, businessType, uri, status, optParam, errorMsg, operTime);
}
@Override
public PageInfoModel<SysOperLog> getOperLogList(int pageNo, int pageSize, String startTime, String endTime) {
if (pageNo == 0 || pageSize == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
public PageInfoModel<SysOperLogVo> getOperLogList(int pageNo, int pageSize) {
if(pageNo == 0 || pageSize == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
List<SysOperLog> records = sysOperLogMapper.getOperLogList(startTime, endTime);
records = records.stream().sorted(Comparator.comparing(SysOperLog::getOperTime, Comparator.reverseOrder())).collect(Collectors.toList());
List<SysOperLog> result = new ArrayList<>();
List<SysOperLogVo> records = sysOperLogMapper.getOperLogList();
List<SysOperLogVo> result = new ArrayList<>();
int begin = (pageNo - 1) * pageSize;
if (begin >= 0 && records.size() > 0) {
result = records.stream().skip(begin).limit(pageSize).collect(Collectors.toList());
}
PageInfoModel<SysOperLog> objectPageInfoModel = new PageInfoModel<>();
PageInfoModel<SysOperLogVo> objectPageInfoModel = new PageInfoModel<>();
objectPageInfoModel.setTotal(records.size());
objectPageInfoModel.setResult(result);
return objectPageInfoModel;
......
......@@ -52,7 +52,7 @@ public class TerminalDeviceServiceImpl implements TerminalDeviceService {
user.setUserId(appId);
user.setUserName(sn);
String token = JwtUtil.createToken(user);
return ResResult.success().record(token);
return ResResult.success().goRecord(token);
} else {
return ResResult.validate_failed();
}
......
package iot.sixiang.license.service.impl;
import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.license.consts.ResultCode;
import iot.sixiang.license.entity.User;
import iot.sixiang.license.handler.IotLicenseException;
import iot.sixiang.license.jwt.UserUtils;
import iot.sixiang.license.mapper.UserMapper;
import iot.sixiang.license.model.BaseResult;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.dto.UpdateNotifyDTO;
import iot.sixiang.license.model.vo.UserVo;
import iot.sixiang.license.service.UserService;
import iot.sixiang.license.util.CommonUtil;
......@@ -21,7 +17,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
......@@ -58,27 +53,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
@Override
public BaseResult updateNotify(UpdateNotifyDTO updateNotifyDTO) {
String notify = updateNotifyDTO.getNotify();
String loginUserId = UserUtils.getLoginUserId();
if (StringUtils.isEmpty(notify) || !Validator.isEmail(notify)) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
if (StringUtils.isEmpty(loginUserId)) {
throw new IotLicenseException(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMsg());
public User getUserById(int userId) {
return userMapper.getUserById(userId);
}
int userId = Integer.parseInt(loginUserId);
User user = new User();
user.setNotify(notify);
user.setUpdateTime(new Date());
@Override
public User getUserByName(String root) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUserId, userId);
int res = userMapper.update(user, wrapper);
if (res > 0) {
return BaseResult.success();
} else {
return BaseResult.failed();
}
wrapper.eq(User::getUserName, root).last("limit 1");
return userMapper.selectOne(wrapper);
}
@Override
......@@ -91,25 +74,18 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public boolean addUser(String userName, String company, String password) {
String notify = null;
if (Validator.isEmail(userName)) {
notify = userName;
}
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(company) || (notify == null && !CommonUtil.regularMessage(userName))) {
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(company) || !CommonUtil.regularMessage(userName)) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
User res = userMapper.getUserByUserName(userName);
if (res != null) {
throw new IotLicenseException(403, "用户名已存在");
}
return userMapper.addUser(userName, company, password, notify);
return userMapper.addUser(userName, company, password);
}
@Override
public boolean updateUser(int userId, String password) {
if (userId == 0 || StringUtils.isEmpty(password)) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
return userMapper.updateUser(userId, password);
public boolean updateUser(User user) {
return userMapper.updateUser(user.getUserId(), user.getPassword());
}
}
package iot.sixiang.license.third_lib;
import iot.sixiang.license.idreader.LibPathUtil;
import iot.sixiang.license.idreader.Safety;
import iot.sixiang.license.util.CommonUtil;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* Title: LibHelper
* Description: TODO
*
* @author tianlai3
* @date 2022-07-17 19:03:09
*/
@Component
public class LibHelper {
private Safety safety;
@PostConstruct
public void init() {
LibPathUtil.libDir = CommonUtil.getServerParentDirectory();
safety = new Safety();
}
public byte[] decodeExtendedPayload(byte[] data, int offset, int length) {
return safety.decodeExtendedPayload(data, offset, length);
}
}
\ No newline at end of file
package iot.sixiang.license.util;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class CodeGenerator {
public static void main(String[] args) {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
// String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\zengtianlai\\test2\\ioc_sixiang_license\\license" + "/src/main/java");
gc.setAuthor("lai");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/iot_license?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("license"); //模块名
pc.setParent("iot.sixiang");
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("sys_oper_log");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
package iot.sixiang.license.util;
import iot.sixiang.license.handler.IotLicenseException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* Title: EmailUtils
* Description:
*
* @author YFW
* @version V1.0
* @date 2020-05-23
*/
@Slf4j
@Component
public class EmailUtils {
Logger logger = LoggerFactory.getLogger(EmailUtils.class);
@Value("${spring.mail.username}")
private String from;
@Resource
public JavaMailSender mailSender;
public void sendSimpleMail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
//发件人
message.setFrom(from);
//目标
message.setTo(to);
//主题
message.setSubject(subject);
//内容
message.setText(content);
try {
mailSender.send(message);
logger.info("一份简单邮件已发送。");
} catch (Exception e) {
logger.error("发送简单邮件时发生异常!", e);
throw new IotLicenseException(405, "短信邮件发送失败");
}
}
}
//package iot.sixiang.license.xss;
//
///**
// * Title: AntiSamyConfig
// * Description: TODO
// *
// * @author tianlai3
// * @date 2022-07-17 01:18:02
// */
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.databind.module.SimpleModule;
//import org.springframework.boot.web.servlet.FilterRegistrationBean;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
//
//import javax.servlet.Filter;
//
//
//@Configuration
//public class AntiSamyConfig {
//
// /**
// * 配置XSS过滤器
// *
// * @return FilterRegistrationBean
// */
// @Bean
// public FilterRegistrationBean<Filter> filterRegistrationBean() {
// FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new XssFilter2());
// filterRegistrationBean.addUrlPatterns("/iot_license/*");
// filterRegistrationBean.setOrder(1);
// return filterRegistrationBean;
// }
//
// /**
// * 用于过滤Json类型数据的解析器
// *
// * @param builder Jackson2ObjectMapperBuilder
// * @return ObjectMapper
// */
// @Bean
// public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
// // 创建解析器
// ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// // 注册解析器
// SimpleModule simpleModule = new SimpleModule("XssStringJsonSerializer");
// simpleModule.addSerializer(new XssRequestWrapper2.XssStringJsonSerializer());
// objectMapper.registerModule(simpleModule);
// return objectMapper;
// }
//}
\ No newline at end of file
package iot.sixiang.license.xss;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
* @Author m33
* @Date 2022/7/17 11:42
* @Description
*/
public class BeanCopyUtil extends BeanUtils {
/**
* 集合数据的拷贝
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
* 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @param callBack: 回调函数
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
copyProperties(source, t);
list.add(t);
}
return list;
}
}
package iot.sixiang.license.xss;
/**
* @Author m33
* @Date 2022/7/17 11:43
* @Description
*/
@FunctionalInterface
public interface BeanCopyUtilCallBack <S, T> {
/**
* 定义默认回调方法
* @param t
* @param s
*/
void callBack(S t, T s);
}
package iot.sixiang.license.xss;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
/**
* @Author m33
* @Date 2022/6/29 13:59
* @Description
*/
@Configuration
public class XSSFilterConfig {
@Bean
@DependsOn("xssFilter")
public FilterRegistrationBean filterRegistrationBean() {
System.out.println("===================filterRegistrationBean");
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("xssFilter");
return registration;
}
}
......@@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
......@@ -25,16 +26,18 @@ public class XssFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(XssFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
public void init(FilterConfig filterConfig) {
LOGGER.info("==============> 进入init XssFilter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(req);
LOGGER.info("========>进入XSS过滤器");
chain.doFilter(xssRequest, response);
chain.doFilter(xssRequest, resp);
LOGGER.info("=========>过滤器XSS执行完");
}
......
//package iot.sixiang.license.xss;
//
//import javax.servlet.*;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//
//
//public class XssFilter2 implements Filter {
//
// private FilterConfig filterConfig;
//
// @Override
// public void init(FilterConfig filterConfig) throws ServletException {
// this.filterConfig = filterConfig;
// }
//
// @Override
// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
// throws IOException, ServletException {
// // 拦截请求,处理XSS过滤
// HttpServletRequest req = (HttpServletRequest) request;
// HttpServletResponse resp = (HttpServletResponse) response;
// XssRequestWrapper2 xssRequest = new XssRequestWrapper2(req);
//
// chain.doFilter(xssRequest, resp);
// }
//
// @Override
// public void destroy() {
// this.filterConfig = null;
// }
//}
\ No newline at end of file
package iot.sixiang.license.xss;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import iot.sixiang.license.consts.ResultCode;
import iot.sixiang.license.handler.IotLicenseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.owasp.esapi.ESAPI;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
......@@ -13,12 +25,121 @@ import static java.util.regex.Pattern.*;
* @Date 2022/7/4 11:24
* @Description
*/
@Slf4j
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* post请求体
*/
private byte[] body;
/**
* 是否是文件上传
*/
private boolean fileUpload = false;
/**
* sql注入正则
*/
private static String badStrReg =
"\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) throws IOException {
super(servletRequest);
String sessionStream = getBodyString(servletRequest);
body = sessionStream.getBytes(StandardCharsets.UTF_8);
}
private String getBodyString(HttpServletRequest httpservletrequest) throws IOException {
StringBuilder sb = new StringBuilder();
InputStream ins = httpservletrequest.getInputStream();
boolean isMultipartContent = ServletFileUpload.isMultipartContent(httpservletrequest);
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(httpservletrequest.getSession().getServletContext());
boolean isMultipart = commonsMultipartResolver.isMultipart(httpservletrequest);
if (isMultipartContent || isMultipart) {
fileUpload = true;
}
try (BufferedReader isr = new BufferedReader(new InputStreamReader(ins, StandardCharsets.UTF_8))) {
String line = "";
while ((line = isr.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
throw e;
}
String res = sb.toString();
return res;
}
/**
* 过滤请求体 json 格式的
*
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream(){
// 非文件上传进行过滤
if (!fileUpload) {
// 获取body中的请求参数
String requestString = new String(body, StandardCharsets.UTF_8);
if(requestString.startsWith("[")) {
List<String> strings = JSONArray.parseArray(requestString, String.class);
for (String string : strings) {
checkSqlAndXss(string);
}
} else {
checkSqlAndXss(new String(body, StandardCharsets.UTF_8));
}
}
// 将请求体参数流转 -- 流读取一次就会消失,所以我们事先读取之后就存在byte数组里边方便流转
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
log.debug("setReadListener");
}
};
}
public void checkSqlAndXss(String str) {
JSONObject json = JSONObject.parseObject(str);
// 校验并过滤xss攻击和sql注入
for (String k : json.keySet()) {
cleanSQLInject(cleanXSS(json.getString(k)));
}
}
/**
* 过滤sql注入 -- 需要增加通配,过滤大小写组合
*
* @param src 单个参数值
* @return
*/
public String cleanSQLInject(String src) {
// 非法sql注入正则
Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);
if (sqlPattern.matcher(src.toUpperCase()).find()) {
log.error("sql注入检查:输入信息存在SQL攻击!");
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), "sql注入检查:参数含有非法攻击字符,已禁止继续访问!!");
}
return src;
}
@Override
......@@ -37,7 +158,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
cleanSQLInject(values[i]);
encodedValues[i] = cleanXSS(values[i]);
}
......@@ -57,6 +178,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
}
cleanSQLInject(value);
return cleanXSS(value);
}
......@@ -74,28 +197,9 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
}
// private String cleanXSS(String value) {
//
// //You'll need to remove the spaces from the html entities below
//
// value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
//
// value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
//
// value = value.replaceAll("'", "& #39;");
//
// value = value.replaceAll("eval\\((.*)\\)", "");
//
// value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
//
// value = value.replaceAll("script", "");
//
// return value;
//
// }
private String cleanXSS(String value) {
if (value != null) {
if (value != null && value.length() != 0) {
// 推荐使用ESAPI库来避免脚本攻击
value = ESAPI.encoder().canonicalize(value);
// 避免空字符串
......@@ -142,7 +246,9 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
// 避免 onXX= 表达式
scriptPattern = Pattern.compile("on.*(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
if (value.length() == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), "参数含有非法攻击字符,已禁止继续访问!!");
}
}
return value;
}
......
//package iot.sixiang.license.xss;
//
//import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.databind.JsonSerializer;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.text.StringEscapeUtils;
//import org.owasp.validator.html.*;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletRequestWrapper;
//import java.io.IOException;
//import java.io.UnsupportedEncodingException;
//import java.net.URLDecoder;
//import java.util.Iterator;
//import java.util.Map;
//import java.util.Objects;
//
///**
// * Title: XssRequestWrapper2
// * Description: TODO
// *
// * @author tianlai3
// * @date 2022-07-16 22:48:55
// */
//@Slf4j
//public class XssRequestWrapper2 extends HttpServletRequestWrapper {
// private static Policy policy = null;
//
// static {
// try {
// // 获取策略文件路径,策略文件需要放到项目的classpath下
// String antiSamyPath = Objects
// .requireNonNull(XssRequestWrapper2.class.getClassLoader().getResource("antisamy-ebay.xml")).getFile();
// log.info(antiSamyPath);
// // 获取的文件路径中有空格时,空格会被替换为%20,在new一个File对象时会出现找不到路径的错误
// // 对路径进行解码以解决该问题
// antiSamyPath = URLDecoder.decode(antiSamyPath, "utf-8");
// log.info(antiSamyPath);
// // 指定策略文件
// policy = Policy.getInstance(antiSamyPath);
// } catch (UnsupportedEncodingException | PolicyException e) {
// log.warn(e.getMessage());
// }
// }
//
// public XssRequestWrapper2(HttpServletRequest request) {
// super(request);
// }
//
// /**
// * 过滤请求头
// *
// * @param name 参数名
// * @return 参数值
// */
// @Override
// public String getHeader(String name) {
// String header = super.getHeader(name);
// // 如果Header为空,则直接返回,否则进行清洗
// return StringUtils.isBlank(header) ? header : xssClean(header);
// }
//
// /**
// * 过滤请求参数
// *
// * @param name 参数名
// * @return 参数值
// */
// @Override
// public String getParameter(String name) {
// String parameter = super.getParameter(name);
// // 如果Parameter为空,则直接返回,否则进行清洗
// return StringUtils.isBlank(parameter) ? parameter : xssClean(parameter);
// }
//
// /**
// * 过滤请求参数(一个参数可以有多个值)
// *
// * @param name 参数名
// * @return 参数值数组
// */
// @Override
// public String[] getParameterValues(String name) {
// String[] parameterValues = super.getParameterValues(name);
// if (parameterValues != null) {
// int length = parameterValues.length;
// String[] newParameterValues = new String[length];
// for (int i = 0; i < length; i++) {
// log.info("AntiSamy清理之前的参数值:" + parameterValues[i]);
// // 清洗参数
// newParameterValues[i] = xssClean(parameterValues[i]);
// log.info("AntiSamy清理之后的参数值:" + newParameterValues[i]);
// }
// return newParameterValues;
// }else{
// return null;
// }
// }
//
//// @Override
//// public String[] getParameterValues(String parameter) {
////
//// String[] values = super.getParameterValues(parameter);
////
//// if (values == null) {
////
//// return null;
////
//// }
////
//// int count = values.length;
////
//// String[] encodedValues = new String[count];
////
//// for (int i = 0; i < count; i++) {
////// cleanSQLInject(values[i]);
//// encodedValues[i] = xssClean(values[i]);
////
//// }
////
//// return encodedValues;
////
//// }
//// @Override
//// public Map<String, String[]> getParameterMap() {
//// Map<String, String[]> requestMap = super.getParameterMap();
////
////
//// requestMap.forEach((key, value) -> {
//// for (int i = 0; i < value.length; i++) {
//// log.info(value[i]);
//// value[i] = xssClean(value[i]);
//// log.info(value[i]);
//// }
//// });
//// return requestMap;
//// }
//
// /**
// * 使用AntiSamy清洗数据
// *
// * @param value 需要清洗的数据
// * @return 清洗后的数据
// */
// private String xssClean(String value) {
// try {
// AntiSamy antiSamy = new AntiSamy();
// // 使用AntiSamy清洗数据
// final CleanResults cleanResults = antiSamy.scan(value, policy);
// // 获得安全的HTML输出
// value = cleanResults.getCleanHTML();
// // 对转义的HTML特殊字符(<、>、"等)进行反转义,因为AntiSamy调用scan方法时会将特殊字符转义
// return StringEscapeUtils.unescapeHtml4(value);
// } catch (ScanException | PolicyException e) {
// log.warn(e.getMessage());
// }
// return value;
// }
//
// /**
// * 通过修改Json序列化的方式来完成Json格式的XSS过滤
// */
// public static class XssStringJsonSerializer extends JsonSerializer<String> {
//
// @Override
// public Class<String> handledType() {
// return String.class;
// }
//
// @Override
// public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// if (!StringUtils.isBlank(value)) {
// try {
// AntiSamy antiSamy = new AntiSamy();
// final CleanResults cleanResults = antiSamy.scan(value, XssRequestWrapper2.policy);
// gen.writeString(StringEscapeUtils.unescapeHtml4(cleanResults.getCleanHTML()));
// } catch (ScanException | PolicyException e) {
// log.warn(e.getMessage());
// }
// }
// }
// }
//}
\ No newline at end of file
package iot.sixiang.license.xss;
import iot.sixiang.license.consts.ResultCode;
import iot.sixiang.license.handler.IotLicenseException;
import lombok.extern.slf4j.Slf4j;
import org.owasp.esapi.ESAPI;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
/**
* Title: XssUtil
* Description: TODO
*
* @author tianlai3
* @date 2022-07-17 15:27:52
*/
@Slf4j
public class XssUtil {
public static String checkXSS(String value) {
if (value != null && value.length() != 0) {
// 推荐使用ESAPI库来避免脚本攻击
value = ESAPI.encoder().canonicalize(value);
// 避免空字符串
value = value.replaceAll("", "");
// 避免script 标签
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免src形式的表达式
//scriptPattern = compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", CASE_INSENSITIVE | MULTILINE | DOTALL);
//value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的 </script> 标签
scriptPattern = Pattern.compile("</script>", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的<script ...> 标签
scriptPattern = Pattern.compile("<script(.*?)>", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 eval(...) 形式表达式
scriptPattern = Pattern.compile("eval\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 e­xpression(...) 表达式
scriptPattern = Pattern.compile("expression\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 javascript: 表达式
scriptPattern = Pattern.compile("javascript:", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 vbscript: 表达式
scriptPattern = Pattern.compile("vbscript:", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 onload= 表达式
scriptPattern = Pattern.compile("onload(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 onXX= 表达式
scriptPattern = Pattern.compile("on.*(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
if (value.length() == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), "参数含有非法攻击字符,已禁止继续访问!!");
}
return value;
} else {
return null;
}
}
}
......@@ -77,9 +77,9 @@ ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator
# ESAPI Authenticator
#
Authenticator.AllowedLoginAttempts=3
Authenticator.MaxOldPasswordHashes=13
Authenticator.MaxOldPasswordHashes=ENC(F0TJ9iT6D4VW8xVjZf9Nqw==)
Authenticator.UsernameParameterName=username
Authenticator.PasswordParameterName=password
Authenticator.PasswordParameterName=ENC(F0TJ9iT6D4VW8xVjZf9Nqw==)
# RememberTokenDuration (in days)
Authenticator.RememberTokenDuration=14
# Session Timeouts (in minutes)
......@@ -304,9 +304,9 @@ Encryptor.KDF.PRF=HmacSHA256
HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
HttpUtilities.UploadTempDir=C:\\temp
# Force flags on cookies, if you use HttpUtilities to set cookies
HttpUtilities.ForceHttpOnlySession=false
#HttpUtilities.ForceHttpOnlySession=false
HttpUtilities.ForceSecureSession=false
HttpUtilities.ForceHttpOnlyCookies=true
#HttpUtilities.ForceHttpOnlyCookies=true
HttpUtilities.ForceSecureCookies=true
# Maximum size of HTTP header key--the validator regex may have additional values.
HttpUtilities.MaxHeaderNameSize=256
......
This diff is collapsed.
......@@ -70,7 +70,6 @@ Slashdot allowed tags taken from "Reply" page:
<attribute name="href" onInvalid="filterTag">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
......
......@@ -8,9 +8,12 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/iot_license?serverTimezone=GMT%2B8
username: root
password: 123456
password: ENC(F0TJ9iT6D4VW8xVjZif9Nqw==)
mybatis-plus:
mapper-locations: classpath:/mapper/**.xml
type-aliases-package: iot.sixiang.license.entity
knife4j:
enable: true
other:
sm4-key: sixiang890123456
\ No newline at end of file
server:
port: 8868
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://rm-wz9w0x7a26q11av687o.mysql.rds.aliyuncs.com:3306/iot_license?serverTimezone=GMT%2B8
username: dada
password: Acc2019123
mybatis-plus:
mapper-locations: classpath:/mapper/**.xml
type-aliases-package: iot.sixiang.license.entity
knife4j:
enable: true
logging:
level:
root: info
\ No newline at end of file
server:
port: 8868
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://rm-wz9w0x7a26q11av687o.mysql.rds.aliyuncs.com:3306/iot_license?serverTimezone=GMT%2B8
username: dada
password: Acc2019123
main:
allow-bean-definition-overriding: true
mybatis-plus:
mapper-locations: classpath:/mapper/**.xml
type-aliases-package: iot.sixiang.license.entity
knife4j:
enable: true
logging:
level:
root: info
\ No newline at end of file
spring:
profiles:
active: test
active: dev
application:
name: iot_license #当前服务的名称
main:
allow-bean-definition-overriding: true
# 这个邮箱部署的时候要改成自己公司的
mail:
host: smtp.mxhichina.com
port: 465
username: dev_team@huahuico.com
password: ENC(eUd8aq15PjmiIF1GBeRwkJJvGZKaAYKu)
# 需要配置成管理员邮箱
to: MAllk33@163.com
default-encoding: UTF-8
properties:
mail:
smtp:
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
fallback: false
## 配置输出日志
logging:
config: classpath:logback-spring.xml
server:
tomcat:
port-header: HEAD,PUT,DELETE,OPTIONS,TRACE,COPY,SEARCH,PROPFIND
cros:
# 需要设置访问白名单
cros_allowed_origins: http://192.168.1.88:8080, http://192.168.1.88:8081, http://localhost:8868, http://localhost:8080, http://192.168.1.54:8080
cros_allowed_method: GET,POST
other:
md5:
salt: PI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SX
error_count:
change_pwd: 5 # 修改密码的最大错误次数
forget_pwd: 5 # 忘记密码的最大错误次数
check_code: 5 # 校验验证码的最大错误次数
code_exp_time: 3 # 验证码失效时间,单位:分钟
rsa:
public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18W2H1hO98dUWf1PNKNWTWmxCyvvy0NOR7iSvp76J0LdzyMJxs8WHVAmRfSGOb9SvpDZhBVx11bhTBqkl1qMzJWzn+F2ZtTCH2nXZcJHwSfLuGqin5FRBYW1WrFkqwg+R80aOuRSrbo0k1bZg3JPkkCxISHieEZPjSV5a4r7+Xopj0a9Dnh3rh4nDmH2p/wvotkx1oMKdhFglYcAITlk9ucEUf+CDuSdTAFFeKg9+fPqwKqWZRJZPQXqV3pGZ1/JS7gPnBFGZojW44eJufkBeiW3pbBvm/cKOkTnb8o4oltYUJsirYSQCCG+sDtxUAuGxuDCv8p+r8dWE1z5+xKclQIDAQAB
private_key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXxbYfWE73x1RZ/U80o1ZNabELK+/LQ05HuJK+nvonQt3PIwnGzxYdUCZF9IY5v1K+kNmEFXHXVuFMGqSXWozMlbOf4XZm1MIfaddlwkfBJ8u4aqKfkVEFhbVasWSrCD5HzRo65FKtujSTVtmDck+SQLEhIeJ4Rk+NJXlrivv5eimPRr0OeHeuHicOYfan/C+i2THWgwp2EWCVhwAhOWT25wRR/4IO5J1MAUV4qD358+rAqpZlElk9BepXekZnX8lLuA+cEUZmiNbjh4m5+QF6JbelsG+b9wo6ROdvyjiiW1hQmyKthJAIIb6wO3FQC4bG4MK/yn6vx1YTXPn7EpyVAgMBAAECggEAR7YQ+kfqLtVThnj2mwLyCtZmndTjZEWhPZrtQmcpsmS5vT7i3+0xZ1qc7cD/3y9j+6u+bvSFmlDondd4/kh85P2X7joLlM9/GNufV9WC7YIhZdAi7i9ooxI2HMc6MtGRiWF0J0B87folwRYrQlF6epv/goh1cQ3FIJ7kxMYzSk0gF0JcmOZn3KH8tMt3t/GK+uVUIycuEQQKsaTTq45nIM7oqhlAwD/M+IO2pGFkLXJ23FzFACI10qBdpn+xL2xFGRO6EE8EAeDslT4OvvN3/vtnSnRNn8CJqfoEG40XO0xrZzH1noI35iPWX1WrN7qFLAhl2oLhu1ZSIA1tz0+I/QKBgQD3X/islXfVmV2XeuHvaf4qcMAdrgLQwtmLlHhFxfFURPh6au8uatDgUA8HWcRACmhtTruytlFRGKKFwZxuQE/LOZh67Uts3GTs5eHN8xvZTL+en+n7B/cCRYrrg3+yAM/k0eezIlk65iW700o+icEHxkwTXhhVBmIROBzpXsVCwwKBgQDfS6kVhgZxLMQePbXUQ1NBr2KbfhXLzceINhsoyWLa1rIk8+9HLSxw8q0zma12Jqkd22OAgkbeLDy+niYPi3pUrWAm8O59Ot1aaOarxMTvEv7+eS+urKId57sli/hQTWsS+xghA4+VfW2+EY++pYyZIp+j+1/Q2ciXWVJy4iv9xwKBgFzW8+kxn2vWxz1WrPzBdtZOwothB0V6G1M7QXhONag+ylKHV4TAKexFn55Onky6mz6K0f7cVeBtsnEonKD0Gf5Xe1aHQEt225ndHMXCe60uFKxfr9y6vIVpvB1vmLkhfOSPsrmUJpDoVzkKr06RPJTCY0LRiag/YQa9XHxpSPcpAoGAKbsiJnudyJjtLhmqWbkbXjNA4n515FjY6YPzH3RDnVJyiKVuGoc+vv0bkYEvAd3HzWSq++FdDTiHQbictFsEyb59McnlSFIv/C2Orptfkq6iKTzMxIBO6/fa6fF2vss5L5rtr33S38VJNTRjAOY/mH74BtV72rRY4LA40G+keRECgYEAiGg0DYxcSGf2bEP1WESYPTTdgS5ke1niIwZ00SgtkIjPSVgTCmf4Tciys6lGSe/Oqnvk24VR6pz07wzcbH92AURVaeqiEvVuVonzA6Yl0jxeOIM31S1BSBJRT8kDijuvwoJu2tPoZG0306KF9L8pyy1Z6cTTmIfGR0NpZCHWPSg=
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="10 seconds">
<!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、 -->
<!-- <logger name="iot.sixiang.license" level="debug" />-->
<!--控制台输出的格式设置 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 控制台输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 只是DEBUG级别以上的日志才显示 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!--文件输出的格式设置 -->
<appender name="ALL_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志日常打印文件 -->
<file>logs/license.log</file>
<!-- 配置日志所生成的目录以及生成文件名的规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/license.log-%d{yyyy-MM-dd}.%i</fileNamePattern>
<!-- 如果按天来回滚,则最大保存时间为365天,365天之前的都将被清理掉 -->
<maxHistory>365</maxHistory>
<!-- 日志总保存量为10GB -->
<totalSizeCap>100GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大128MB时会被压缩和切割 -->
<maxFileSize>40 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<!-- 文件输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
<prudent>false</prudent>
</appender>
<!--文件输出的格式设置 -->
<appender name="MSG_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志日常打印文件 -->
<file>logs/message.log</file>
<!-- 配置日志所生成的目录以及生成文件名的规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/message.log-%d{yyyy-MM-dd}.%i</fileNamePattern>
<!-- 如果按天来回滚,则最大保存时间为365天,365天之前的都将被清理掉 -->
<maxHistory>365</maxHistory>
<!-- 日志总保存量为10GB -->
<totalSizeCap>100GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大128MB时会被压缩和切割 -->
<maxFileSize>40 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 此日志文档只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 文件输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
<prudent>false</prudent>
</appender>
<!-- Enable FILE and STDOUT appenders for all log messages. By default,
only log at level INFO and above. -->
<!--这里选择INFO就代表,进行INFO级别输出记录,那么在控制台也好,log文件也好只记录INFO及以上级别的日志,这里相当于第一道设置-->
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="ALL_FILE" />
<appender-ref ref="MSG_FILE" />
</root>
</configuration>
\ No newline at end of file
......@@ -7,14 +7,11 @@
<if test="null != sn and '' != sn">
and sn like concat('%',#{sn},'%')
</if>
<if test="null != status">
<if test="null != status and status == 0">
and status = #{status}
</if>
<if test="startTime != null and startTime != ''">
AND create_time &gt; #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND create_time &lt; #{endTime}
<if test="null != status and status == 1">
and (status = #{status} or status is null)
</if>
and deleted = 0
order by create_time desc
......
......@@ -5,14 +5,7 @@
insert into sys_oper_log(title, business_type, uri, status, opt_param, error_msg, oper_time) values (#{title},#{businessType},#{uri},#{status},#{optParam},#{errorMsg},#{operTime})
</insert>
<select id="getOperLogList" resultType="iot.sixiang.license.entity.SysOperLog">
select id, title, business_type, uri, status, opt_param, error_msg, oper_time from sys_oper_log
where 1=1
<if test="startTime != null and startTime != ''">
AND oper_time &gt; #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND oper_time &lt; #{endTime}
</if>
<select id="getOperLogList" resultType="iot.sixiang.license.model.vo.SysOperLogVo">
select id, title, business_type, uri, status, error_msg, oper_time from sys_oper_log order by oper_time desc
</select>
</mapper>
......@@ -35,7 +35,11 @@
</select>
<select id="getUserByUserName" resultType="iot.sixiang.license.entity.User">
select user_id from user where user_name = #{userName}
select * from user where user_name = #{userName}
</select>
<select id="getUserById" resultType="iot.sixiang.license.entity.User">
select * from user where user_id = #{userId}
</select>
</mapper>
package iot.sixiang.license;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
/**
* Created by M=54G
* Date 9/14/22 3:08 PM
* Description
*/
@SpringBootTest
@ActiveProfiles({"test-acc"})
@Slf4j
public class BaseTest {
protected void log(Object object) {
log.info(JSON.toJSONString(object));
}
}
\ No newline at end of file
package iot.sixiang.license.object.data;
import lombok.Data;
/**
* Created by M=54G
* Date 11/11/22 10:08 AM
* Description
*/
@Data
public class AuthData {
private String app_id;
private String sn;
private String sign;
}
\ No newline at end of file
package iot.sixiang.license.service;
import iot.sixiang.license.BaseTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
/**
* Created by M=54G
* Date 11/23/22 3:39 PM
* Description
*/
public class PmsUseServiceTest extends BaseTest {
@Resource
private PmsUseService pmsUseService;
@Test
void addLog() {
log(pmsUseService.createUseLog("abcd"));
}
@Test
void updateLog() {
pmsUseService.success(1);
}
}
\ No newline at end of file
package iot.sixiang.license.util;
import org.apache.http.util.TextUtils;
public class ByteHelper {
/**
* src:源数组
* srcPos:源数组要复制的起始位置
* dest:目的数组
* destPos:目的数组放置的起始位置
* length:要复制的长度
*
* @param src
* @param begin
* @param count
* @return
*/
public static byte[] subBytes(byte[] src, int begin, int count) {
byte[] bs = new byte[count];
System.arraycopy(src, begin, bs, 0, count);
return bs;
}
/**
* 字节码转化十六进制
*
* @author xzb
*/
public static String fromBytesToHex(byte[] resultBytes) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < resultBytes.length; i++) {
if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
builder.append("0").append(Integer.toHexString(0xFF & resultBytes[i]));
} else {
builder.append(Integer.toHexString(0xFF & resultBytes[i]));
}
}
return builder.toString();
}
/**
* byte[] 转为16进制String
*/
public static String Bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
/**
* 转化十六进制编码为字符串
*
* @param s
* @return
*/
public static String toStringHex(String s) {
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "utf-8");//UTF-16le:Not
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
/***
* 合并数组
* @param byteList
* @return
*/
public static byte[] byteMerger(byte[]... byteList) {
int lengthByte = 0;
for (int i = 0; i < byteList.length; i++) {
lengthByte += byteList[i].length;
}
byte[] allByte = new byte[lengthByte];
int countLength = 0;
for (int i = 0; i < byteList.length; i++) {
byte[] b = byteList[i];
System.arraycopy(b, 0, allByte, countLength, b.length);
countLength += b.length;
}
return allByte;
}
/**
* 字符串转16进制
*
* @param string
* @return
*/
public static String stringToHexString(String string) {
char[] c = new char[string.length()];
c = string.toCharArray();
String hesStr = "";
for (int i = 0; i < c.length; i++) {
hesStr = hesStr + Integer.toHexString(c[i]);
}
return hesStr;
}
/**
* 字符串转化成为16进制字符串
*
* @param s
* @return
*/
public static String strTo16(String s) {
String str = "";
for (int i = 0; i < s.length(); i++) {
int ch = (int) s.charAt(i);
String s4 = Integer.toHexString(ch);
str = str + s4;
}
return str;
}
/**
* hex字符串转byte数组
*
* @param inHex 待转换的Hex字符串
* @return 转换后的byte数组结果
*/
public static byte[] hexToByteArray(String inHex, int len) {
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1) {
//奇数
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
//偶数
result = new byte[(hexlen / 2)];
}
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2));
j++;
}
return result;
}
public static long bytes2long(byte[] bs) throws Exception {
int bytes = bs.length;
if (bytes > 1) {
if ((bytes % 2) != 0 || bytes > 8) {
throw new Exception("not support");
}
}
switch (bytes) {
case 0:
return 0;
case 1:
return (long) ((bs[0] & 0xff));
case 2:
return (long) ((bs[0] & 0xff) << 8 | (bs[1] & 0xff));
case 4:
return (long) ((bs[0] & 0xffL) << 24 | (bs[1] & 0xffL) << 16 | (bs[2] & 0xffL) << 8 | (bs[3] & 0xffL));
case 8:
return (long) ((bs[0] & 0xffL) << 56 | (bs[1] & 0xffL) << 48 | (bs[2] & 0xffL) << 40 | (bs[3] & 0xffL) << 32 |
(bs[4] & 0xffL) << 24 | (bs[5] & 0xffL) << 16 | (bs[6] & 0xffL) << 8 | (bs[7] & 0xffL));
default:
throw new Exception("not support");
}
//return 0;
}
public static long bytes2long(byte[] bs, int offset) {
return (long) ((bs[7 + offset] & 0xffL) << 56 | (bs[6 + offset] & 0xffL) << 48 | (bs[5 + offset] & 0xffL) << 40 | (bs[4 + offset] & 0xffL) << 32 |
(bs[3 + offset] & 0xffL) << 24 | (bs[2 + offset] & 0xffL) << 16 | (bs[1 + offset] & 0xffL) << 8 | (bs[0 + offset] & 0xffL));
}
public static byte[] hexStrToBytes(String hexStr, int len) {
if (TextUtils.isEmpty(hexStr) || hexStr.length() == 0) {
return null;
}
if (hexStr.length() % 2 == 1) {
hexStr = "0" + hexStr;
}
byte[] result = new byte[len];
char[] chars = hexStr.toCharArray();
int hexlen = hexStr.length();
if (hexlen > len)
hexlen = len;
for (int i = 0; i < hexlen - 1; i++) {
result[i] = (byte) (charToByte(chars[i]) << 4 | charToByte(chars[i + 1]));
}
return result;
}
private static byte charToByte(char c) {
String chars = "0123456789ABCDEF";
byte b = (byte) chars.indexOf(c);
return b;
}
/**
* Hex字符串转byte
*
* @param inHex 待转换的Hex字符串
* @return 转换后的byte
*/
public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
}
}
package iot.sixiang.license.util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
/**
* Title: HmacShaUtils
* Description:
*
* @author YFW
* @version V1.0
* @date 2022-03-14
*/
public class HmacShaUtils {
private static final String HMAC_ALGORITHM = "hmacsha1";
private static final String secretKey = "90d2fca50ea8ed5472c5776c9fc53699";
/**
* 使用HMAC_ALGORITHM加密。
*
* @param content,明文。
* @param secret,密钥。
* @return 密文。
*/
public static String encrypt(String content, String secret) {
if (PubUtils.isNull(secret)) secret = secretKey;
try {
byte[] text = content.getBytes(StandardCharsets.UTF_8);
byte[] key = secret.getBytes(StandardCharsets.UTF_8);
SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return byte2hex(mac.doFinal(text));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 二进制转十六进制字符串。
*
* @param b,二进制数组。
* @return 十六进制字符串。
*/
public static String byte2hex(byte[] b) {
StringBuffer sb = new StringBuffer();
for (int n = 0; b != null && n < b.length; n++) {
String stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1) {
sb.append('0');
}
sb.append(stmp);
}
return sb.toString().toUpperCase();
}
}
package iot.sixiang.license.util.sm4;
public class SM4Context {
public int mode;
public long[] sk;
public boolean isPadding;
public SM4Context() {
this.mode = 1;
this.isPadding = true;
this.sk = new long[32];
}
}
package iot.sixiang.license.util.sm4;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SM4Utils {
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public boolean isHexString() {
return hexString;
}
public void setHexString(boolean hexString) {
this.hexString = hexString;
}
private String secretKey = "";
public String getIv() {
return iv;
}
public void setIv(String iv) {
this.iv = iv;
}
private String iv = "";
private boolean hexString = false;
public SM4Utils() {
}
public String encryptData_ECB(String plainText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
} else {
keyBytes = secretKey.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes("UTF-8"));
String cipherText = Base64.getEncoder().encodeToString(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
return cipherText;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_ECB(String cipherText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
} else {
keyBytes = secretKey.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Base64.getDecoder().decode(cipherText));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String encryptData_CBC(String plainText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
ivBytes = ByteUtil.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("UTF-8"));
String cipherText = Base64.getEncoder().encodeToString(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
return cipherText;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_CBC(String cipherText) {
try {
SM4Context ctx = new SM4Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = ByteUtil.hexStringToBytes(secretKey);
ivBytes = ByteUtil.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.getDecoder().decode(cipherText));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment