refactor: 2.0 版本重构

新增:
1. 新增EventBus
2. 新增 邮箱、手机、用户名 + 密码登陆
3. 新增 邮箱 + 验证码 登录
4. 新增 手机号 + 验证码 登录
5. 新增个人修改手机号 前置身份校验
6. 新增个人修改邮箱 前置身份校验
7. 新增个人中心忘记密码 前置身份校验
8. 新增使用ResultWrapper 代替 ResultVo 返回数据

优化:
1. 优化接口加密
2. 优化CrudService实现
3. 变更自动日志记录模式到自定义记录
4. 优化导出Excel模式为认证模式
5. 优化用户Redis缓存
6. 移除Shiro,变更使用SpringSecurity 作为权限验证

升级/修复:
1. 修复 SecurityCache 缓存穿透BUG
2. 升级 mybatis-plus 版本至 3.5.2 修复若干CVE
3. 升级 springboot 版本至 2.5.6 修复若干CVE
4. 升级 mysql版本至8.0.28  修复 CVE-2022-21363
5. 升级 guava 版本至 30.0.android 修复 修复 CVE-2020-8908
6. 升级 bouncycastle 版本至 1.69 修复 Cxa9261daf-3755
7. 升级 protobuf-java 版本至 3.18.2 修复 CVE-2021-22569
8. 升级 logback 版本至 修复 CVE-2021-42550
pull/19/head
Parker 2 years ago
parent 077196058c
commit edd6dcec59

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright [2020] [OPSLI 快速开发平台 https://www.opsli.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

File diff suppressed because one or more lines are too long

@ -0,0 +1,14 @@
FROM mysql:8.0.19
MAINTAINER opsli.com
LABEL version=V1.3.3
LABEL description=OPSLI-快速开发平台
LABEL qqGroup=724850675
ENV TZ=Asia/Shanghai
# 切换为上海时区
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone
COPY ./opsli-boot.sql /docker-entrypoint-initdb.d

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@ version: '3.3'
services:
# 构建 MySQL数据库 这里不指定数据库文件 防止误操作 等隐患问题
opsli-boot-mysql:
build: ./db-file
build: ./db-file/2.0版本
image: opsli-boot-mysql
restart: always
environment:
@ -57,4 +57,4 @@ services:
volumes:
- /www/wwwroot/demo.opsli.bedebug.com/backend/run:/usr/local/opsli/opsli-boot #挂载目录
ports:
- "7000:7000"
- "7000:7000"

@ -10,7 +10,7 @@ import java.io.Serializable;
/**
*
*
* @author
* @author Parker
* @date 2021-01-24 12:48
**/
@Data

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.encrypt;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021-01-24 12:48
**/
@Data
public class EncryptModel implements Serializable {
private static final long serialVersionUID = 1L;
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(2000)
@ApiModelProperty(value = "加密数据")
private String encryptData;
}

@ -1,207 +0,0 @@
package org.opsli.api.base.result;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
/**
* API
* Feign
* @JsonProperty null
*
* @date 202051510:40:54
* @author Parker
*/
@Data
@ApiModel(value="视图层返回Api对象",
description="视图层返回Api对象 success:成功状态 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultVo<T> implements Serializable {
private static final long serialVersionUID = 1L;
/** 默认成功信息 */
public static final String DEF_SUCCESS_MSG = "操作成功!";
/** 默认失败信息 */
public static final String DEF_ERROR_MSG = "操作失败!";
/** 成功状态 */
@ApiModelProperty(value = "成功状态")
@JsonProperty("success")
private boolean success;
/** 消息 */
@ApiModelProperty(value = "消息")
@JsonProperty("msg")
private String msg;
/** 状态码 */
@ApiModelProperty(value = "状态码")
@JsonProperty("code")
private Integer code;
/** 时间戳 */
@ApiModelProperty(value = "时间戳")
@JsonProperty("timestamp")
private Long timestamp;
/** 数据对象 */
@ApiModelProperty(value = "数据")
@JsonProperty("data")
private T data;
public T getData() {
return data;
}
public ResultVo<T> setData(T data) {
this.data = data;
return this;
}
/**
* Json
* @return String
*/
public String toJsonStr(){
return JSONObject.toJSONString(this);
}
// ===========================================
/**
*
*/
public ResultVo() {
// 初始化值
this.success = true;
this.msg = DEF_SUCCESS_MSG;
this.code = HttpStatus.OK.value();
this.timestamp = System.currentTimeMillis();
}
// ================================== 静态方法 ===================================
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success() {
return new ResultVo<>();
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success(String msg) {
ResultVo<Object> ret = new ResultVo<>();
ret.setMsg(msg);
return ret;
}
/**
*
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setCode(code);
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error() {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, DEF_ERROR_MSG, null);
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error(String msg) {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, msg, null);
}
/**
*
* @param code
* @param msg
* @return ResultVo<T>
*/
@JsonIgnore
public static ResultVo<Object> error(Integer code, String msg) {
return ResultVo.error(code, msg, null);
}
/**
*
* @param code
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> error(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setCode(code);
ret.setData(data);
ret.setSuccess(false);
return ret;
}
}

@ -0,0 +1,263 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import org.opsli.common.base.msg.BaseMsg;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021123015:31:41
*/
@Data
@Builder
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "基础返回实体",
description="视图层返回Api对象 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultWrapper<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@ApiModelProperty(name = "msg", dataType = "string", value = "响应信息")
private String msg;
/**
* 0-1
*/
@ApiModelProperty(name = "code", dataType = "int", value = "响应码")
private int code;
/**
*
*/
@ApiModelProperty(name = "data", dataType = "object", value = "数据内容")
private T data;
/**
*
*/
@ApiModelProperty(name = "timestamp", dataType = "long", value = "时间戳")
private long timestamp;
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapperByMsg(String msg) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(msg)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper() {
return getSuccessResultWrapper(null);
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(StateCodeEnum.SUCCESS.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper() {
return getErrorResultWrapper(null);
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.ERROR.getCode())
.msg(StateCodeEnum.ERROR.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(StateCodeEnum stateCode) {
return getCustomResultWrapper(null, stateCode);
}
/**
* 便
* @param data
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, StateCodeEnum stateCode) {
return ResultWrapper.<T>builder()
.code(stateCode.getCode())
.msg(stateCode.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(BaseMsg baseMsg) {
return getCustomResultWrapper(null, baseMsg);
}
/**
* 便
* @param data
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, BaseMsg baseMsg) {
return ResultWrapper.<T>builder()
.code(baseMsg.getCode())
.msg(baseMsg.getMessage())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(null)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* @param resultWrapper
* @param <T>
* @return boolean
*/
public static <T> boolean isSuccess(ResultWrapper<T> resultWrapper) {
if(null == resultWrapper){
return false;
}
return StateCodeEnum.SUCCESS.getCode() == resultWrapper.getCode();
}
/**
*
*
* @author Parker
* @date 2021123015:29:29
*/
@Getter
@AllArgsConstructor
public enum StateCodeEnum {
/** 请求状态枚举 */
SUCCESS(0, "请求成功"),
FAILURE(-1, "操作失败"),
ERROR(-1, "服务器异常");
private final int code;
private final String msg;
}
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.gentest.carinfo;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -25,7 +25,7 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
/**
*
* Api
*
* API @GetMapping @PostMapping
* Mapping Controller
@ -33,98 +33,97 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
*
*
* @author Parker
* @date 2020-12-20 20:12:57
* @date 2022-08-06 23:53:30
*/
public interface TestCarRestApi {
/** 标题 */
String TITLE = "汽车信息管理";
String TITLE = "测试汽车";
/** 子标题 */
String SUB_TITLE = "汽车信息";
String SUB_TITLE = "测试汽车";
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestCarModel> get(TestCarModel model);
ResultWrapper<TestCarModel> get(TestCarModel model);
/**
*
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestCarModel model);
ResultWrapper<?> insert(@RequestBody TestCarModel model);
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestCarModel model);
ResultWrapper<?> update(@RequestBody TestCarModel model);
/**
*
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param response response
* Excel
* @param request request
* @return ResultWrapper
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
@PostMapping("/importExcel")
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
}
}

@ -15,11 +15,8 @@
*/
package org.opsli.api.web.gentest.user;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -48,20 +45,20 @@ public interface TestUserRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestUserModel> get(TestUserModel model);
ResultWrapper<TestUserModel> get(TestUserModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,64 @@ public interface TestUserRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestUserModel model);
ResultWrapper<?> insert(@RequestBody TestUserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestUserModel model);
ResultWrapper<?> update(@RequestBody TestUserModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.area;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.area.SysAreaModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,80 +48,57 @@ public interface SysAreaRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<SysAreaModel> get(SysAreaModel model);
ResultWrapper<SysAreaModel> get(SysAreaModel model);
/**
*
* @param parentId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTree")
ResultVo<?> findTree(String parentId);
ResultWrapper<?> findTree(String parentId);
/**
*
* @param deep
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeAll")
ResultVo<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep);
ResultWrapper<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysAreaModel model);
ResultWrapper<?> insert(@RequestBody SysAreaModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody SysAreaModel model);
ResultWrapper<?> update(@RequestBody SysAreaModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,20 +48,20 @@ public interface DictApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<DictModel> get(DictModel model);
ResultWrapper<DictModel> get(DictModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,65 +70,42 @@ public interface DictApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictModel model);
ResultWrapper<?> insert(@RequestBody DictModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody DictModel model);
ResultWrapper<?> update(@RequestBody DictModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
/**
*
*
* @param typeCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getDictListByCode")
ResultVo<?> getDictListByCode(String typeCode);
ResultWrapper<?> getDictListByCode(String typeCode);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictDetailModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -49,20 +49,20 @@ public interface DictDetailApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<DictDetailModel> get(DictDetailModel model);
ResultWrapper<DictDetailModel> get(DictDetailModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -71,57 +71,34 @@ public interface DictDetailApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictDetailModel model);
ResultWrapper<?> insert(@RequestBody DictDetailModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody DictDetailModel model);
ResultWrapper<?> update(@RequestBody DictDetailModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
// ================================
@ -130,9 +107,9 @@ public interface DictDetailApi {
*
*
* @param typeCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findListByTypeCode")
ResultVo<List<DictDetailModel>> findListByTypeCode(String typeCode);
ResultWrapper<List<DictDetailModel>> findListByTypeCode(String typeCode);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,10 +48,10 @@ public interface LoginLogsApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -45,20 +45,20 @@ public interface LogsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<LogsModel> get(LogsModel model);
ResultWrapper<LogsModel> get(LogsModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -68,8 +68,8 @@ public interface LogsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<?> insert(LogsModel model);
ResultWrapper<?> insert(LogsModel model);
}

@ -0,0 +1,92 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opsli.api.wrapper.system.logs.OperationLogModel;
/**
* Api
*
* API @GetMapping @PostMapping
* Mapping Controller
*
*
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
public interface OperationLogRestApi {
/** 标题 */
String TITLE = "行为日志";
/** 子标题 */
String SUB_TITLE = "行为日志";
/**
*
* @param model
* @return ResultWrapper
*/
@GetMapping("/get")
ResultWrapper<OperationLogModel> get(OperationLogModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.menu;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuFullModel;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.springframework.web.bind.annotation.GetMapping;
@ -52,71 +52,71 @@ public interface MenuApi {
*
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreePage")
ResultVo<?> findMenuTreePage(HttpServletRequest request);
ResultWrapper<?> findMenuTreePage(HttpServletRequest request);
/**
*
*
* @param parentId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreePageByLazy")
ResultVo<?> findMenuTreePageByLazy(String parentId);
ResultWrapper<?> findMenuTreePageByLazy(String parentId);
/**
*
* @param parentId ID
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreeByLazy")
ResultVo<?> findMenuTreeByLazy(String parentId, String id);
ResultWrapper<?> findMenuTreeByLazy(String parentId, String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/findMenuTree")
ResultVo<?> findMenuTree();
ResultWrapper<?> findMenuTree();
/**
* -
*
* @param label
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getMenuAndPermsTree")
ResultVo<?> getMenuAndPermsTree(String label);
ResultWrapper<?> getMenuAndPermsTree(String label);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findList")
ResultVo<List<MenuModel>> findList();
ResultWrapper<List<MenuModel>> findList();
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<MenuModel> get(MenuModel model);
ResultWrapper<MenuModel> get(MenuModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -125,58 +125,34 @@ public interface MenuApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody MenuModel model);
ResultWrapper<?> insert(@RequestBody MenuModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody MenuModel model);
ResultWrapper<?> update(@RequestBody MenuModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
// ================= 普通
@ -184,14 +160,14 @@ public interface MenuApi {
/**
*
* @param permissions
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<MenuModel> getByPermissions(String permissions);
ResultWrapper<MenuModel> getByPermissions(String permissions);
/**
*
* @param menuFullModel
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel);
ResultWrapper<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel);
}

@ -17,11 +17,8 @@
package org.opsli.api.web.system.options;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -55,20 +52,20 @@ public interface OptionsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<OptionsModel> get(OptionsModel model);
ResultWrapper<OptionsModel> get(OptionsModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -77,108 +74,105 @@ public interface OptionsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody OptionsModel model);
ResultWrapper<?> insert(@RequestBody OptionsModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody OptionsModel model);
ResultWrapper<?> update(@RequestBody OptionsModel model);
/**
*
* @param params Map
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateOptions")
ResultVo<?> updateOptions(@RequestBody Map<String, String> params);
ResultWrapper<?> updateOptions(@RequestBody Map<String, String> params);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param request request
* @param response response
* @return ResultVo
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
* @return ResultVo
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
// ==========================
/**
*
* @param optionCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getByCode")
ResultVo<OptionsModel> getByCode(String optionCode);
ResultWrapper<OptionsModel> getByCode(String optionCode);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAllOptions")
ResultVo<Map<String, OptionsModel>> findAllOptions();
ResultWrapper<Map<String, OptionsModel>> findAllOptions();
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAll")
ResultVo<List<OptionsModel>> findAll();
ResultWrapper<List<OptionsModel>> findAll();
/**
*
*
* @param type
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/createCrypto")
ResultVo<?> createCrypto(String type);
ResultWrapper<?> createCrypto(String type);
}

@ -15,11 +15,8 @@
*/
package org.opsli.api.web.system.org;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -50,90 +47,67 @@ public interface SysOrgRestApi {
*
* @param parentId ID
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeLazy")
ResultVo<?> findTreeLazy(String parentId, String id);
ResultWrapper<?> findTreeLazy(String parentId, String id);
/**
*
* @param isGen
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeByDef")
ResultVo<?> findTreeByDef(boolean isGen, String id);
ResultWrapper<?> findTreeByDef(boolean isGen, String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeByDefWithUserToLike")
ResultVo<?> findTreeByDefWithUserToLike();
ResultWrapper<?> findTreeByDefWithUserToLike();
// ================
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<SysOrgModel> get(SysOrgModel model);
ResultWrapper<SysOrgModel> get(SysOrgModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysOrgModel model);
ResultWrapper<?> insert(@RequestBody SysOrgModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody SysOrgModel model);
ResultWrapper<?> update(@RequestBody SysOrgModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface RoleApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<RoleModel> get(RoleModel model);
ResultWrapper<RoleModel> get(RoleModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,63 @@ public interface RoleApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody RoleModel model);
ResultWrapper<?> insert(@RequestBody RoleModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody RoleModel model);
ResultWrapper<?> update(@RequestBody RoleModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping;
@ -49,18 +49,18 @@ public interface RoleMenuRefApi {
/**
*
* @param model Id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getPerms")
ResultVo<?> getPerms(RoleMenuRefModel model);
ResultWrapper<?> getPerms(RoleMenuRefModel model);
/**
*
* @param model roleId Id
* @param model permsIds Id
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setPerms")
ResultVo<?> setPerms(@RequestBody RoleMenuRefModel model);
ResultWrapper<?> setPerms(@RequestBody RoleMenuRefModel model);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.system.tenant;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.tenant.TenantModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TenantApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TenantModel> get(TenantModel model);
ResultWrapper<TenantModel> get(TenantModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,57 +67,65 @@ public interface TenantApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TenantModel model);
ResultWrapper<?> insert(@RequestBody TenantModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TenantModel model);
ResultWrapper<?> update(@RequestBody TenantModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/**
@ -128,18 +133,18 @@ public interface TenantApi {
*
* @param tenantId ID
* @param enable
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/enableTenant")
ResultVo<?> enableTenant(String tenantId, String enable);
ResultWrapper<?> enableTenant(String tenantId, String enable);
// =========================
/**
*
* @param tenantId
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getTenantByUsable")
ResultVo<TenantModel> getTenantByUsable(String tenantId);
ResultWrapper<TenantModel> getTenantByUsable(String tenantId);
}

@ -15,14 +15,12 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.encrypt.EncryptModel;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.opsli.api.wrapper.system.user.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -51,97 +49,123 @@ public interface UserApi {
/**
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getInfo")
ResultVo<UserInfo> getInfo(HttpServletRequest request);
ResultWrapper<UserInfo> getInfo(HttpServletRequest request);
/**
*
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getInfoById")
ResultVo<UserInfo> getInfoById(String userId);
ResultWrapper<UserInfo> getInfoById(String userId);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getOrg")
ResultVo<?> getOrg();
ResultWrapper<?> getOrg();
/**
*
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getOrgByUserId")
ResultVo<?> getOrgByUserId(String userId);
ResultWrapper<?> getOrgByUserId(String userId);
/**
* userId Id
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getRoleIdsByUserId")
ResultVo<List<String>> getRoleIdsByUserId(String userId);
ResultWrapper<List<String>> getRoleIdsByUserId(String userId);
/**
* ID
*
* @param encryptModel
* @return ResultVo
*/
@PostMapping("/updatePasswordById")
ResultWrapper<?> updatePasswordById(@RequestBody EncryptModel encryptModel);
/**
*
* @param userPassword
* @return ResultVo
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePassword")
ResultVo<?> updatePassword(@RequestBody UserPassword userPassword);
ResultWrapper<?> updatePassword(@RequestBody EncryptModel encryptModel);
/**
* ID
*
* @param userPassword
* @return ResultVo
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePasswordById")
ResultVo<?> updatePasswordById(@RequestBody ToUserPassword userPassword);
@PostMapping("/updateEmail")
ResultWrapper<?> updateEmail(@RequestBody EncryptModel encryptModel);
/**
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updateMobile")
ResultWrapper<?> updateMobile(@RequestBody EncryptModel encryptModel);
/**
* ID
*
* @param userId ID
* @return ResultVo
* @param encryptModel ID
* @return ResultWrapper
*/
@PostMapping("/resetPasswordById")
ResultVo<?> resetPasswordById(String userId);
ResultWrapper<?> resetPasswordById(@RequestBody EncryptModel encryptModel);
/**
*
*
* @param userId ID
* @param enable
* @return ResultVo
* @param encryptModel EnableUserModel
* @return ResultWrapper
*/
@PostMapping("/enableAccount")
ResultVo<?> enableAccount(String userId, String enable);
ResultWrapper<?> enableAccount(@RequestBody EncryptModel encryptModel);
/**
*
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePasswordByForget")
ResultWrapper<?> updatePasswordByForget(@RequestBody EncryptModel encryptModel);
/**
*
* @param userAvatarModel
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateAvatar")
ResultVo<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel);
ResultWrapper<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<UserModel> get(UserModel model);
ResultWrapper<UserModel> get(UserModel model);
/**
*
@ -149,10 +173,10 @@ public interface UserApi {
* @param pageSize
* @param orgIdGroup ID
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "orgIdGroup") String orgIdGroup,
@ -164,10 +188,10 @@ public interface UserApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPageByTenant")
ResultVo<?> findPageByTenant(
ResultWrapper<?> findPageByTenant(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -178,91 +202,114 @@ public interface UserApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody UserModel model);
ResultWrapper<?> insert(@RequestBody UserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody UserModel model);
ResultWrapper<?> update(@RequestBody UserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateSelf")
ResultVo<?> updateSelf(@RequestBody UserModel model);
ResultWrapper<?> updateSelf(@RequestBody UserModel model);
/**
*
* @param id ID
* @return ResultVo
* @param encryptModel id ID
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(@RequestBody EncryptModel encryptModel);
/**
*
* @param ids ID
* @return ResultVo
* @param encryptModel ids ID
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(@RequestBody EncryptModel encryptModel);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/**
*
* @param tenantId ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/switchTenant")
ResultVo<?> switchTenant(String tenantId);
ResultWrapper<?> switchTenant(String tenantId);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/switchOneself")
ResultVo<?> switchOneself();
ResultWrapper<?> switchOneself();
/**
* username
* @param username
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getUserByUsername")
ResultVo<UserModel> getUserByUsername(String username);
ResultWrapper<UserModel> getUserByUsername(String username);
/**
*
* @param mobile
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByMobile(String mobile);
/**
*
* @param email
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByEmail(String email);

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.org.SysOrgModel;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.api.wrapper.system.user.UserOrgRefWebModel;
@ -47,25 +47,25 @@ public interface UserOrgRefApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setOrg")
ResultVo<?> setOrg(@RequestBody UserOrgRefWebModel model);
ResultWrapper<?> setOrg(@RequestBody UserOrgRefWebModel model);
/**
* ID
* @param userId ID
* @return List
*/
ResultVo<List<UserOrgRefModel>> findListByUserId(String userId);
ResultWrapper<List<UserOrgRefModel>> findListByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<UserOrgRefModel> getDefOrgByUserId(String userId);
ResultWrapper<UserOrgRefModel> getDefOrgByUserId(String userId);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel;
@ -48,50 +48,50 @@ public interface UserRoleRefApi {
/**
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getRoles")
ResultVo<?> getRoles(String userId);
ResultWrapper<?> getRoles(String userId);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setRoles")
ResultVo<?> setRoles(@RequestBody UserRoleRefModel model);
ResultWrapper<?> setRoles(@RequestBody UserRoleRefModel model);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<List<String>> getRolesByUserId(String userId);
ResultWrapper<List<String>> getRolesByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<RoleModel> getDefRoleByUserId(String userId);
ResultWrapper<RoleModel> getDefRoleByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/queryAllPerms")
ResultVo<List<String>> getAllPerms(String userId);
ResultWrapper<List<String>> getAllPerms(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/queryAllPerms")
ResultVo<List<MenuModel>> getMenuListByUserId(String userId);
ResultWrapper<List<MenuModel>> getMenuListByUserId(String userId);
}

@ -1,8 +1,9 @@
package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest;
@ -28,93 +29,93 @@ public interface TestApi {
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/sendMail")
ResultVo<?> sendMail();
ResultWrapper<?> sendMail();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/sendMsg")
ResultVo<?> sendMsg();
ResultWrapper<?> sendMsg();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/redisTest")
ResultVo<?> redisTest();
ResultWrapper<?> redisTest();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/testLock")
ResultVo<?> testLock();
ResultWrapper<?> testLock();
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/insert")
ResultVo<TestModel> insert(TestModel entity);
ResultWrapper<TestModel> insert(TestModel entity);
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/update")
ResultVo<TestModel> update(TestModel entity);
ResultWrapper<TestModel> update(TestModel entity);
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestModel> get(TestModel entity);
ResultWrapper<TestModel> get(TestModel entity);
/**
*
* @param id id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/delAll")
ResultVo<?> delAll();
ResultWrapper<?> delAll();
/**
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findList")
ResultVo<List<TestModel>> findList(HttpServletRequest request);
ResultWrapper<List<TestModel>> findList(HttpServletRequest request);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAllList")
ResultVo<List<TestModel>> findAllList();
ResultWrapper<List<TestModel>> findAllList();
/**
@ -123,10 +124,10 @@ public interface TestApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -134,29 +135,36 @@ public interface TestApi {
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
*
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TestRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestModel> get(TestModel model);
ResultWrapper<TestModel> get(TestModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,65 @@ public interface TestRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestModel model);
ResultWrapper<?> insert(@RequestBody TestModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestModel model);
ResultWrapper<?> update(@RequestBody TestModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,6 +15,7 @@
*/
package org.opsli.api.wrapper.gentest.carinfo;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
@ -23,17 +24,18 @@ import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
*
*
* @author Parker
* @date 2020-12-20 20:12:57
*/
* Model
*
* @author Parker
* @date 2022-08-06 23:53:30
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TestCarModel extends ApiWrapper {
@ -42,7 +44,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车名称")
@ExcelProperty(value = "汽车名称", order = 1)
@ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20)
private String carName;
@ -50,7 +55,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车类型")
@ExcelProperty(value = "汽车类型", order = 2)
@ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20)
private String carType;
@ -58,7 +66,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车品牌")
@ExcelProperty(value = "汽车品牌", order = 3)
@ExcelInfo
@Validator({ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE
})
@ValidatorLenMax(50)
private String carBrand;
@ -66,6 +76,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "生产日期")
@ExcelProperty(value = "生产日期", order = 4)
@ExcelInfo
@Validator({
ValidatorType.IS_NOT_NULL
})
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date produceData;
@ -74,9 +87,12 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "是否启用")
@ExcelProperty(value = "是否启用", order = 5)
@ExcelInfo( dictType = "no_yes" )
@Validator({
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(1)
private String izUsable;
}
}

@ -71,4 +71,10 @@ public class LoginLogsModel extends ApiWrapper {
@ApiModelProperty(value = "用户代理")
private String userAgent;
/**
*
*/
@ApiModelProperty(value = "登陆来源")
private String loginFrom;
}

@ -0,0 +1,132 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.logs;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* Model
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class OperationLogModel extends ApiWrapper {
/** 多租户字段 */
private String tenantId;
/** 日志等级 */
@ApiModelProperty(value = "日志等级")
@ExcelProperty(value = "日志等级", order = 1)
@ExcelInfo( dictType = "log_level" )
@ValidatorLenMax(8)
private String level;
/** 被操作的系统模块 */
@ApiModelProperty(value = "被操作的系统模块")
@ExcelProperty(value = "被操作的系统模块", order = 2)
@ExcelInfo( dictType = "log_model_type" )
@ValidatorLenMax(20)
private String moduleId;
/** 方法名 */
@ApiModelProperty(value = "方法名")
@ExcelProperty(value = "方法名", order = 3)
@ExcelInfo
@ValidatorLenMax(100)
private String method;
/** 参数 */
@ApiModelProperty(value = "参数")
@ExcelProperty(value = "参数", order = 4)
@ExcelInfo
@ValidatorLenMax(20000)
private String args;
/** 操作人id */
@ApiModelProperty(value = "操作人id")
@ExcelProperty(value = "操作人id", order = 5)
@ExcelInfo
@ValidatorLenMax(19)
private String userId;
/** 操作账号 */
@ApiModelProperty(value = "操作账号")
@ExcelProperty(value = "操作账号", order = 6)
@ExcelInfo
@ValidatorLenMax(32)
private String username;
/** 操作人真实名称 */
@ApiModelProperty(value = "操作人真实名称")
@ExcelProperty(value = "操作人真实名称", order = 7)
@ExcelInfo
@ValidatorLenMax(50)
private String realName;
/** 日志描述 */
@ApiModelProperty(value = "日志描述")
@ExcelProperty(value = "日志描述", order = 8)
@ExcelInfo
@ValidatorLenMax(255)
private String description;
/** 操作类型 */
@ApiModelProperty(value = "操作类型")
@ExcelProperty(value = "操作类型", order = 9)
@ExcelInfo( dictType = "log_operation_type" )
@ValidatorLenMax(20)
private String operationType;
/** 方法运行时间 */
@ApiModelProperty(value = "方法运行时间")
@ExcelProperty(value = "方法运行时间", order = 10)
@ExcelInfo
@ValidatorLenMax(19)
private String runTime;
/** 方法返回值 */
@ApiModelProperty(value = "方法返回值")
@ExcelProperty(value = "方法返回值", order = 11)
@ExcelInfo
@ValidatorLenMax(20000)
private String returnValue;
/** 日志请求类型 */
@ApiModelProperty(value = "日志请求类型")
@ExcelProperty(value = "日志请求类型", order = 12)
@ExcelInfo( dictType = "log_type" )
@ValidatorLenMax(8)
private String logType;
}

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class EnableUserModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(50)
private String userId;
/** 是否启用 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(10)
private String enabled;
}

@ -51,12 +51,6 @@ public class ToUserPassword implements Serializable {
@ValidatorLenMax(50)
private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserEmailModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(50)
private String email;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserMobileModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
@ValidatorLenMax(50)
private String mobile;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2020-09-16 17:33
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ExcelIgnoreUnannotated
public class UpdateUserPasswordByForgetModel implements Serializable {
private static final long serialVersionUID = 1L;
/** 新密码 */
@ApiModelProperty(value = "新密码")
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_SECURITY_PASSWORD})
@ValidatorLenMin(6)
@ValidatorLenMax(50)
private String newPassword;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -56,12 +56,12 @@ public class UserInfo extends ApiWrapper {
/** 手机 */
@ApiModelProperty(value = "手机")
@Validator({ValidatorType.IS_MOBILE})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile;
/** 邮箱 */
@ApiModelProperty(value = "邮箱")
@Validator({ValidatorType.IS_EMAIL})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
private String email;
/** 工号 */

@ -60,12 +60,6 @@ public class UserModel extends ApiWrapper {
@ValidatorLenMax(1)
private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 是否启用 */
@ApiModelProperty(value = "是否启用")
@ExcelIgnore
@ -84,14 +78,14 @@ public class UserModel extends ApiWrapper {
@ApiModelProperty(value = "手机")
@ExcelProperty(value = "手机", order = 2)
@ExcelInfo
@Validator({ValidatorType.IS_MOBILE})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile;
/** 邮箱 */
@ApiModelProperty(value = "邮箱")
@ExcelProperty(value = "邮箱", order = 3)
@ExcelInfo
@Validator({ValidatorType.IS_EMAIL})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(100)
private String email;

@ -58,12 +58,6 @@ public class UserPassword implements Serializable {
@ValidatorLenMax(50)
private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore

@ -64,12 +64,6 @@ public class UserWebModel extends ApiWrapper {
@ValidatorLenMax(1)
private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 启用状态 */
@ApiModelProperty(value = "启用状态")
@ExcelIgnore

@ -22,4 +22,4 @@
</dependencies>
</project>
</project>

@ -70,13 +70,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
// -------------------------------------------
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success(String msg) {
ResultVoMap j = new ResultVoMap();
j.setMsg(msg);
return j;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore//
public static ResultVoMap error(String msg) {
ResultVoMap j = new ResultVoMap();
j.setSuccess(false);
@ -84,14 +91,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
return j;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success(Map<String, Object> map) {
ResultVoMap restResponse = new ResultVoMap();
restResponse.putAll(map);
return restResponse;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success() {
return new ResultVoMap();
}

@ -3,7 +3,7 @@ package org.opsli.common.constants;
/**
* Redis
* {}
* @author
* @author Parker
* @date 2021/12/10 19:52
*/
public final class RedisConstants {
@ -47,9 +47,12 @@ public final class RedisConstants {
/** 用户ID 和 菜单 */
public static final String PREFIX_USER_ID_MENUS = "kv#{}:user_id:menus:";
/** 用户名 */
public static final String PREFIX_USERNAME = "kv#{}:username:";
/** 用户名 + 用户ID */
public static final String PREFIX_USER_USERNAME = "kv#{}:user:username_id:";
/** 手机号 + 用户ID */
public static final String PREFIX_USER_MOBILE = "kv#{}:user:mobile_id:";
/** 邮箱 + 用户ID */
public static final String PREFIX_USER_EMAIL = "kv#{}:user:email_id:";
/** 票据 */
@ -61,8 +64,21 @@ public final class RedisConstants {
/** 账号失败锁定KEY */
public static final String PREFIX_ACCOUNT_SLIP_LOCK = "kv#{}:account:slip:lock:";
/** 临时邮箱验证码 */
public static final String PREFIX_TMP_EMAIL_CODE_NAME = "kv#{}:verification:email:code:";
/** 临时手机验证码 */
public static final String PREFIX_TMP_MOBILE_CODE_NAME = "kv#{}:verification:mobile:code:";
/** 验证码凭证 用于验证码二次校验(唯一流水号 increment) */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NUM_NAME = "kv#{}:verification:certificate-num";
/** 验证码凭证 用于验证码二次校验 */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NAME = "kv#{}:verification:certificate:";
/** Excel 导出(唯一流水号 increment) */
public static final String PREFIX_TMP_EXCEL_EXPORT_NUM_NAME = "kv#{}:excel-export-num";
/** Excel 导出 凭证 */
public static final String PREFIX_TMP_EXCEL_EXPORT_NAME = "kv#{}:excel-export:";
private RedisConstants(){}
}

@ -17,6 +17,9 @@ public final class SignConstants {
/** 租户ID */
public static final String TENANT_ID = "tenantId";
/** 登陆来源 */
public static final String LOGIN_FROM = "loginFrom";
/** 时间戳 */
public static final String TIMESTAMP = "timestamp";

@ -19,7 +19,7 @@ package org.opsli.common.enums;
/**
*
*
* @author :
* @author : Parker
* @date : 2020-09-17 23:40
*/
public enum DictType {

@ -0,0 +1,77 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.bean.BeanUtil;
import java.util.Arrays;
/**
*
*
* @author
* @date 2020-09-17 23:40
*/
public enum LoginFromEnum {
/** 账号 */
PC("0"),
/** APP - 安卓 */
APP_ANDROID("1"),
/** APP - 苹果 */
APP_IOS("2"),
/** 微信小程序 */
WX_APPLET("3"),
/** h5 */
H5("4"),
/** 未知 */
UNKNOWN("-1"),
;
private final static String FILED_NAME = "loginFrom";
/***/
private final String type;
LoginFromEnum(String type){
this.type = type;
}
public String getType() {
return this.type;
}
public static LoginFromEnum getByCode(String code){
return Arrays.stream(LoginFromEnum.values())
.filter(value -> value.getType().equals(code))
.findFirst().orElse(LoginFromEnum.UNKNOWN);
}
public static LoginFromEnum getByBean(Object bean){
if(null == bean || !BeanUtil.isBean(bean.getClass())){
return LoginFromEnum.UNKNOWN;
}
Object fieldValue = BeanUtil.getFieldValue(bean, FILED_NAME);
if(null == fieldValue){
return LoginFromEnum.UNKNOWN;
}
return getByCode((String) fieldValue);
}
}

@ -0,0 +1,61 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
/**
*
*
* @author Parker
* @date 2022-07-21 2:07 PM
**/
public enum LoginModelType {
/** 未知 */
UNKNOWN,
/** 账号 */
ACCOUNT,
/** 手机 */
MOBILE,
/** 邮箱 */
EMAIL
;
public static LoginModelType getTypeByStr(String principal){
if(StrUtil.isBlank(principal)){
return UNKNOWN;
}
// 手机号
if(Validator.isMobile(principal)){
return MOBILE;
}
// 邮箱
else if(Validator.isEmail(principal)){
return EMAIL;
}
// 默认账号
return ACCOUNT;
}
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Optional;
/**
*
*
* @author
* @date 2022-08-01 12:49 PM
**/
@AllArgsConstructor
@Getter
public enum VerificationTypeEnum {
/** 类型 */
LOGIN("0"),
AUTH("1")
;
/** 类型 */
private final String type;
public static Optional<VerificationTypeEnum> getEnumByType(String type){
VerificationTypeEnum[] types = values();
for (VerificationTypeEnum typeEnum : types) {
if(typeEnum.type.equals(type)){
return Optional.of(typeEnum);
}
}
return Optional.empty();
}
}

@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线线
* 202111214:07:54 线
*
* @author
* @author Parker
* @date 2020-12-10 10:36
*/
@Slf4j

@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线
* 线线
*
* @author
* @author Parker
* @date 2020-12-10 10:36
*/
@Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread;
import cn.hutool.core.util.StrUtil;
@ -14,7 +29,7 @@ import java.util.function.Function;
/**
* 线 - 线
*
* @author
* @author Parker
* @date 2020-10-08 10:24
*/
@Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread;
import cn.hutool.core.thread.ThreadUtil;
@ -11,7 +26,7 @@ import java.util.concurrent.ExecutorService;
/**
* 线
*
* @author
* @author Parker
* @date 2021/8/27 17:00
*/
@Slf4j

@ -0,0 +1,388 @@
package org.opsli.common.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Hashids designed for Generating short hashes from numbers (like YouTube and Bitly), obfuscate
* database IDs, use them as forgotten password hashes, invitation codes, store shard numbers.
* <p>
* This is implementation of http://hashids.org v1.0.0 version.
*
* This implementation is immutable, thread-safe, no lock is necessary.
*
* @author <a href="mailto:fanweixiao@gmail.com">fanweixiao</a>
* @author <a href="mailto:terciofilho@gmail.com">Tercio Gaudencio Filho</a>
* @since 0.3.3
*/
public class HashIdsUtil {
/**
* Max number that can be encoded with Hashids.
*/
public static final long MAX_NUMBER = 9007199254740992L;
private static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final String DEFAULT_SEPS = "cfhistuCFHISTU";
private static final String DEFAULT_SALT = "";
private static final int DEFAULT_MIN_HASH_LENGTH = 0;
private static final int MIN_ALPHABET_LENGTH = 16;
private static final double SEP_DIV = 3.5;
private static final int GUARD_DIV = 12;
private final String salt;
private final int minHashLength;
private final String alphabet;
private final String seps;
private final String guards;
public HashIdsUtil() {
this(DEFAULT_SALT);
}
public HashIdsUtil(String salt) {
this(salt, 0);
}
public HashIdsUtil(String salt, int minHashLength) {
this(salt, minHashLength, DEFAULT_ALPHABET);
}
public HashIdsUtil(String salt, int minHashLength, String alphabet) {
this.salt = salt != null ? salt : DEFAULT_SALT;
this.minHashLength = minHashLength > 0 ? minHashLength : DEFAULT_MIN_HASH_LENGTH;
final StringBuilder uniqueAlphabet = new StringBuilder();
for (int i = 0; i < alphabet.length(); i++) {
if (uniqueAlphabet.indexOf(String.valueOf(alphabet.charAt(i))) == -1) {
uniqueAlphabet.append(alphabet.charAt(i));
}
}
alphabet = uniqueAlphabet.toString();
if (alphabet.length() < MIN_ALPHABET_LENGTH) {
throw new IllegalArgumentException(
"alphabet must contain at least " + MIN_ALPHABET_LENGTH + " unique characters");
}
if (alphabet.contains(" ")) {
throw new IllegalArgumentException("alphabet cannot contains spaces");
}
// seps should contain only characters present in alphabet;
// alphabet should not contains seps
String seps = DEFAULT_SEPS;
for (int i = 0; i < seps.length(); i++) {
final int j = alphabet.indexOf(seps.charAt(i));
if (j == -1) {
seps = seps.substring(0, i) + " " + seps.substring(i + 1);
} else {
alphabet = alphabet.substring(0, j) + " " + alphabet.substring(j + 1);
}
}
alphabet = alphabet.replaceAll("\\s+", "");
seps = seps.replaceAll("\\s+", "");
seps = HashIdsUtil.consistentShuffle(seps, this.salt);
if ((seps.isEmpty()) || (((float) alphabet.length() / seps.length()) > SEP_DIV)) {
int seps_len = (int) Math.ceil(alphabet.length() / SEP_DIV);
if (seps_len == 1) {
seps_len++;
}
if (seps_len > seps.length()) {
final int diff = seps_len - seps.length();
seps += alphabet.substring(0, diff);
alphabet = alphabet.substring(diff);
} else {
seps = seps.substring(0, seps_len);
}
}
alphabet = HashIdsUtil.consistentShuffle(alphabet, this.salt);
// use double to round up
final int guardCount = (int) Math.ceil((double) alphabet.length() / GUARD_DIV);
String guards;
if (alphabet.length() < 3) {
guards = seps.substring(0, guardCount);
seps = seps.substring(guardCount);
} else {
guards = alphabet.substring(0, guardCount);
alphabet = alphabet.substring(guardCount);
}
this.guards = guards;
this.alphabet = alphabet;
this.seps = seps;
}
/**
* Encrypt numbers to string
*
* @param numbers
* the numbers to encrypt
* @return the encrypt string
*/
public String encode(long... numbers) {
if (numbers.length == 0) {
return "";
}
for (final long number : numbers) {
if (number < 0) {
return "";
}
if (number > MAX_NUMBER) {
throw new IllegalArgumentException("number can not be greater than " + MAX_NUMBER + "L");
}
}
return this._encode(numbers);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public long[] decode(String hash) {
if (hash.isEmpty()) {
return new long[0];
}
String validChars = this.alphabet + this.guards + this.seps;
for (int i = 0; i < hash.length(); i++) {
if(validChars.indexOf(hash.charAt(i)) == -1) {
return new long[0];
}
}
return this._decode(hash, this.alphabet);
}
/**
* Encrypt hexa to string
*
* @param hexa
* the hexa to encrypt
* @return the encrypt string
*/
public String encodeHex(String hexa) {
if (!hexa.matches("^[0-9a-fA-F]+$")) {
return "";
}
final List<Long> matched = new ArrayList<Long>();
final Matcher matcher = Pattern.compile("[\\w\\W]{1,12}").matcher(hexa);
while (matcher.find()) {
matched.add(Long.parseLong("1" + matcher.group(), 16));
}
// conversion
final long[] result = new long[matched.size()];
for (int i = 0; i < matched.size(); i++) {
result[i] = matched.get(i);
}
return this.encode(result);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public String decodeHex(String hash) {
final StringBuilder result = new StringBuilder();
final long[] numbers = this.decode(hash);
for (final long number : numbers) {
result.append(Long.toHexString(number).substring(1));
}
return result.toString();
}
public static int checkedCast(long value) {
final int result = (int) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/* Private methods */
private String _encode(long... numbers) {
long numberHashInt = 0;
for (int i = 0; i < numbers.length; i++) {
numberHashInt += (numbers[i] % (i + 100));
}
String alphabet = this.alphabet;
final char ret = alphabet.charAt((int) (numberHashInt % alphabet.length()));
long num;
long sepsIndex, guardIndex;
String buffer;
final StringBuilder ret_strB = new StringBuilder(this.minHashLength);
ret_strB.append(ret);
char guard;
for (int i = 0; i < numbers.length; i++) {
num = numbers[i];
buffer = ret + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
final String last = HashIdsUtil.hash(num, alphabet);
ret_strB.append(last);
if (i + 1 < numbers.length) {
if (last.length() > 0) {
num %= (last.charAt(0) + i);
sepsIndex = (int) (num % this.seps.length());
} else {
sepsIndex = 0;
}
ret_strB.append(this.seps.charAt((int) sepsIndex));
}
}
String ret_str = ret_strB.toString();
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(0))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str = guard + ret_str;
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(2))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str += guard;
}
}
final int halfLen = alphabet.length() / 2;
while (ret_str.length() < this.minHashLength) {
alphabet = HashIdsUtil.consistentShuffle(alphabet, alphabet);
ret_str = alphabet.substring(halfLen) + ret_str + alphabet.substring(0, halfLen);
final int excess = ret_str.length() - this.minHashLength;
if (excess > 0) {
final int start_pos = excess / 2;
ret_str = ret_str.substring(start_pos, start_pos + this.minHashLength);
}
}
return ret_str;
}
private long[] _decode(String hash, String alphabet) {
final ArrayList<Long> ret = new ArrayList<Long>();
int i = 0;
final String regexp = "[" + this.guards + "]";
String hashBreakdown = hash.replaceAll(regexp, " ");
String[] hashArray = hashBreakdown.split(" ");
if (hashArray.length == 3 || hashArray.length == 2) {
i = 1;
}
if (hashArray.length > 0) {
hashBreakdown = hashArray[i];
if (!hashBreakdown.isEmpty()) {
final char lottery = hashBreakdown.charAt(0);
hashBreakdown = hashBreakdown.substring(1);
hashBreakdown = hashBreakdown.replaceAll("[" + this.seps + "]", " ");
hashArray = hashBreakdown.split(" ");
String subHash, buffer;
for (final String aHashArray : hashArray) {
subHash = aHashArray;
buffer = lottery + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
ret.add(HashIdsUtil.unhash(subHash, alphabet));
}
}
}
// transform from List<Long> to long[]
long[] arr = new long[ret.size()];
for (int k = 0; k < arr.length; k++) {
arr[k] = ret.get(k);
}
if (!this.encode(arr).equals(hash)) {
arr = new long[0];
}
return arr;
}
private static String consistentShuffle(String alphabet, String salt) {
if (salt.length() <= 0) {
return alphabet;
}
int asc_val, j;
final char[] tmpArr = alphabet.toCharArray();
for (int i = tmpArr.length - 1, v = 0, p = 0; i > 0; i--, v++) {
v %= salt.length();
asc_val = salt.charAt(v);
p += asc_val;
j = (asc_val + v + p) % i;
final char tmp = tmpArr[j];
tmpArr[j] = tmpArr[i];
tmpArr[i] = tmp;
}
return new String(tmpArr);
}
private static String hash(long input, String alphabet) {
String hash = "";
final int alphabetLen = alphabet.length();
do {
final int index = (int) (input % alphabetLen);
if (index >= 0 && index < alphabet.length()) {
hash = alphabet.charAt(index) + hash;
}
input /= alphabetLen;
} while (input > 0);
return hash;
}
private static Long unhash(String input, String alphabet) {
long number = 0, pos;
for (int i = 0; i < input.length(); i++) {
pos = alphabet.indexOf(input.charAt(i));
number = number * alphabet.length() + pos;
}
return number;
}
/**
* Get Hashid algorithm version.
*
* @return Hashids algorithm version implemented.
*/
public String getVersion() {
return "1.0.0";
}
}

@ -15,6 +15,8 @@
*/
package org.opsli.common.utils;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
@ -25,7 +27,6 @@ import org.opsli.common.thread.AsyncProcessExecutor;
import org.opsli.common.thread.AsyncProcessExecutorFactory;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -39,6 +40,8 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public final class RateLimiterUtil {
/** 默认IP */
public static final String DEFAULT_IP = "unknown";
/** 默认QPS */
public static final double DEFAULT_QPS = 10d;
/** 默认缓存个数 超出后流量自动清理 */
@ -46,7 +49,7 @@ public final class RateLimiterUtil {
/** 默认缓存时效 超出后自动清理 */
private static final int DEFAULT_CACHE_TIME = 5;
/** 默认等待时长 */
private static final int DEFAULT_WAIT = 5000;
private static final int DEFAULT_WAIT = 500;
/** 限流器单机缓存 */
private static final Cache<String, Map<String, RateLimiterUtil.RateLimiterInner> > LFU_CACHE;
@ -108,6 +111,11 @@ public final class RateLimiterUtil {
*/
@SuppressWarnings("UnstableApiUsage")
public static boolean enter(String clientIpAddress, String resource, Double dfQps) {
// IP 为空补偿器
if(StrUtil.isBlank(clientIpAddress)){
clientIpAddress = DEFAULT_IP;
}
// 计时器
long t1 = System.currentTimeMillis();
@ -152,7 +160,7 @@ public final class RateLimiterUtil {
RateLimiter rateLimiter = rateLimiterObj.getRateLimiter();
//非阻塞
if (!rateLimiter.tryAcquire(Duration.ofMillis(DEFAULT_WAIT))) {
if (!rateLimiter.tryAcquire(DEFAULT_WAIT, TimeUnit.MILLISECONDS)) {
//限速中,提示用户
log.error("限流器 - 访问频繁 耗时: "+ (System.currentTimeMillis() - t1) + "ms, IP地址: " + clientIpAddress + ", URI: " + resource);
return false;
@ -183,18 +191,40 @@ public final class RateLimiterUtil {
public static void main(String[] args) {
int count = 500;
RateLimiterUtil.removeIp("127.0.0.1");
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor();
for (int i = 0; i < count; i++) {
normalExecutor.put(()->{
boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d);
System.out.println(enter);
});
// int count = 500;
// RateLimiterUtil.removeIp("127.0.0.1");
// AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor();
// for (int i = 0; i < count; i++) {
// normalExecutor.put(()->{
// RateLimiter rateLimiter = RateLimiter.create(1);
//
//
// boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d);
// System.out.println(enter);
// });
// }
// normalExecutor.execute();
int count = 3;
RateLimiter rateLimiter = RateLimiter.create(count);
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createWaitExecutor();
int num = 0;
while (true){
System.out.println("------------"+ (++num) +"------------");
for (int i = 0; i < count+1; i++) {
normalExecutor.put(()->{
boolean tryAcquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
System.out.println(tryAcquire);
});
}
normalExecutor.execute();
ThreadUtil.sleep(1100);
}
normalExecutor.execute();
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.utils;
import cn.hutool.core.util.RandomUtil;
/**
*
* <a href="https://huzb.me/2018/03/23/%E7%AE%80%E5%8D%95%E7%9A%84%E5%AF%86%E7%A0%81%E5%AD%A6%E7%94%9F%E6%88%90%E5%94%AF%E4%B8%80%E9%82%80%E8%AF%B7%E7%A0%81">...</a>
*
* @author Parker
* @date 20220711 14:07
*/
public final class UniqueStrGeneratorUtils {
private static final String BEGIN_SALT = "opsli_2022_begin";
private static final String END_SALT = "opsli_2022_end";
private static final String CONTENT_SALT = "opsli_2022";
private static final HashIdsUtil DISTURB_HASH_ID_BEGIN = new HashIdsUtil(BEGIN_SALT, 2);
private static final HashIdsUtil DISTURB_HASH_ID_END = new HashIdsUtil(END_SALT, 3);
private static final HashIdsUtil CONTENT_HASH_ID = new HashIdsUtil(CONTENT_SALT, 7);
/** 生成 */
public static String generator(long i) {
int begin = RandomUtil.randomInt(0, 10);
int end = RandomUtil.randomInt(10, 100);
String disturbHashIdBeginStr = DISTURB_HASH_ID_BEGIN.encode(begin);
String disturbHashIdEndStr = DISTURB_HASH_ID_END.encode(end);
String contentHashIdStr = CONTENT_HASH_ID.encode(i);
return disturbHashIdBeginStr + contentHashIdStr + disturbHashIdEndStr;
}
}

@ -48,6 +48,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入短信插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-sms</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redis插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
@ -55,6 +62,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入Security插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-security</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redisson插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
@ -78,12 +92,6 @@
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 开始 ———————————————————— -->
<!-- ShiroRedis包 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
</dependency>
<!-- captcha 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
@ -96,6 +104,11 @@
<artifactId>java-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
</dependency>
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 结束 ———————————————————— -->
<!-- ———————————————————— 集成数据库相关配置 - 开始 ———————————————————— -->
@ -127,7 +140,20 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
<exclusions>
<!-- 修复 CVE-2021-22569 -->
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 修复 CVE-2021-22569 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<!-- sqlserver-->
@ -149,6 +175,7 @@
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
<version>${postgresql.version}</version>
</dependency>
<!-- ———————————————————— 集成数据库相关配置 - 结束 ———————————————————— -->

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Cors
*
* @author Parker
* @date 2022071412:57:33
**/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
*
*
* @param registry registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(7200);
}
}

@ -15,7 +15,8 @@
*/
package org.opsli.core.autoconfigure.conf;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.opsli.core.filters.interceptor.MybatisAutoFillInterceptor;
@ -35,13 +36,20 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
public class MyBatisPlusConfig {
/***
*
* @return
/**
*
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表更新与删除插件
//mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
/**

@ -0,0 +1,141 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.opsli.core.security.filter.JwtAuthenticationTokenFilter;
import org.opsli.core.security.service.UidUserDetailDetailServiceImpl;
import org.opsli.plugins.security.exception.handler.AccessDeniedHandlerImpl;
import org.opsli.plugins.security.exception.handler.AuthenticationEntryPointImpl;
import org.opsli.plugins.security.properties.AuthProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.util.List;
import java.util.Map;
/**
* Security
*
* @author Parker
* @date 2022071412:57:33
**/
@AllArgsConstructor
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthProperties authProperties;
private final AccessDeniedHandlerImpl accessDeniedHandler;
private final AuthenticationEntryPointImpl authenticationEntryPoint;
private final UidUserDetailDetailServiceImpl uidUserDetailDetailService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
// 默认关闭 Security 的 xss防护与系统本身的 xss防护冲突
.xssProtection().disable()
// 允许Iframe加载
.frameOptions().disable()
.and()
// 关闭csrf token认证不需要csrf防护
.csrf().disable();
// 初始化 initAuthorizeRequests
this.initAuthorizeRequests(http);
}
/**
* URL
* @param http http
*/
private void initAuthorizeRequests(HttpSecurity http) throws Exception {
// 设置URL 未登陆前可访问URL
List<String> anonymousList = authProperties.getUrlExclusion().getAnonymous();
if(null != anonymousList){
String[] urlExclusionArray = anonymousList.toArray(new String[0]);
http.authorizeRequests()
// URL 未登陆前可访问
.antMatchers(urlExclusionArray).anonymous();
}
// 设置URL白名单
List<String> permitAll = authProperties.getUrlExclusion().getPermitAll();
if(null != permitAll){
String[] urlExclusionArray = permitAll.toArray(new String[0]);
http.authorizeRequests()
// URL 白名单
.antMatchers(urlExclusionArray).permitAll();
}
// 除上面外的所有请求全部需要鉴权认证
http.authorizeRequests()
.anyRequest().authenticated();
// 添加过滤器
// 注意 自定义 Filter 不要交给 Spring管理
http.addFilterBefore(new JwtAuthenticationTokenFilter(uidUserDetailDetailService),
UsernamePasswordAuthenticationFilter.class);
// 异常处理
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
}
/**
*
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected AuthenticationManager authenticationManager() {
// 设置 多Provider
Map<String, AuthenticationProvider> providerMap =
SpringUtil.getBeansOfType(AuthenticationProvider.class);
List<AuthenticationProvider> authenticationProviderList =
Lists.newArrayListWithCapacity(providerMap.size());
for (Map.Entry<String, AuthenticationProvider> providerEntry : providerMap.entrySet()) {
authenticationProviderList.add(providerEntry.getValue());
}
ProviderManager authenticationManager = new ProviderManager(authenticationProviderList);
//不擦除认证密码擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
authenticationManager.setEraseCredentialsAfterAuthentication(false);
return authenticationManager;
}
}

@ -1,198 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.opsli.core.autoconfigure.properties.ApiPathProperties;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.security.shiro.authenticator.CustomModularRealmAuthenticator;
import org.opsli.core.security.shiro.filter.CustomShiroFilter;
import org.opsli.core.security.shiro.realm.FlagRealm;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Shiro
*
* token -
*
* @author Parker
* @date 2017-04-20 18:33
*/
@Configuration
public class ShiroConfig {
/**
* filer
* @param securityManager
* @return ShiroFilterFactoryBean
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager,
GlobalProperties globalProperties, ApiPathProperties apiPathProperties) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
Map<String, Filter> filters = Maps.newHashMapWithExpectedSize(1);
filters.put("last_filter", new CustomShiroFilter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = Maps.newLinkedHashMap();
// 加载排除URL
if(globalProperties.getAuth() != null &&
globalProperties.getAuth().getToken() != null){
Set<String> urlExclusion = globalProperties.getAuth().getToken().getUrlExclusion();
if(CollUtil.isNotEmpty(urlExclusion)){
for (String excUrl : urlExclusion) {
filterMap.put(excUrl, "anon");
}
}
}
// 登录接口拦截
filterMap.put("/system/login", "anon");
filterMap.put("/system/publicKey", "anon");
filterMap.put("/system/slipCount", "anon");
filterMap.put("/captcha*", "anon");
// 导出Excel\模版 不做自动拦截 手动拦截
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/exportExcel", "anon");
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/importExcel/template", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/app/**", "anon");
filterMap.put("/swagger/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/doc.html", "anon");
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/**", "last_filter");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean("sessionManager")
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookieEnabled(true);
return sessionManager;
}
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setSessionManager(sessionManager);
// 设置验证器为自定义验证器
securityManager.setAuthenticator(modularRealmAuthenticator());
List<Realm> realms = Lists.newArrayList();
// 拿到state包下 实现了 FlagRealm 接口的,所有子类
Set<Class<?>> clazzSet = ClassUtil.scanPackageBySuper(
FlagRealm.class.getPackage().getName(),
FlagRealm.class
);
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
continue;
}
try {
realms.add((Realm) aClass.newInstance());
} catch (Exception ignored){ }
}
if(CollUtil.isNotEmpty(realms)){
// 追加 Realms
securityManager.setRealms(realms);
}
return securityManager;
}
/**
* Realm使
*/
@Bean("modularRealmAuthenticator")
public ModularRealmAuthenticator modularRealmAuthenticator(){
CustomModularRealmAuthenticator authenticator = new CustomModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
// ===================== 固定三板斧 =====================
// 其实 没有 Spring Security 配置起来简单
//
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean("defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
proxyCreator.setUsePrefix(true);
proxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
return proxyCreator;
}
/**
* shiro
* @param securityManager
* @return AuthorizationAttributeSourceAdvisor
*/
@Bean("authorizationAttributeSourceAdvisor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}

@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -67,23 +68,18 @@ public class SpringWebMvcConfig implements WebMvcConfigurer, WebMvcRegistrations
/**
*
* @return CorsFilter
*
* @param registry registry
*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
/* 是否允许请求带有验证信息 */
corsConfiguration.setAllowCredentials(true);
/* 允许访问的客户端域名 */
corsConfiguration.addAllowedOrigin("*");
/* 允许服务端访问的客户端请求头 */
corsConfiguration.addAllowedHeader("*");
/* 允许访问的方法名,GET POST等 */
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOriginPatterns("*")
// .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("*")
// .allowCredentials(true)
// .maxAge(7200);
// }
@Override
public void addInterceptors(InterceptorRegistry registry) {

@ -90,9 +90,6 @@ public class GlobalProperties {
/** 有效时间 (分钟)*/
private Integer effectiveTime;
/** 排除URL*/
private Set<String> urlExclusion;
}
/**

@ -0,0 +1,43 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Token
*
* @author Parker
* @date 2020-09-15
*/
@Component
@ConfigurationProperties(prefix = TokenProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)
public class TokenProperties {
public static final String PROP_PREFIX = "opsli.auth.token";
/** 盐 */
private String secret;
/** 有效时间 */
private int effectiveTime;
}

@ -16,7 +16,6 @@
package org.opsli.core.base.controller;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
@ -24,36 +23,42 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.annotation.RequiresPermissionsCus;
import org.opsli.common.annotation.hotdata.EnableHotData;
import org.opsli.common.constants.RedisConstants;
import org.opsli.common.constants.TreeConstants;
import org.opsli.common.enums.ExcelOperate;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.exception.TokenException;
import org.opsli.common.utils.OutputStreamUtil;
import org.opsli.common.utils.UniqueStrGeneratorUtils;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.base.entity.BaseEntity;
import org.opsli.core.base.entity.HasChildren;
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.core.cache.CacheUtil;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.opsli.core.security.shiro.realm.JwtRealm;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.ExcelUtil;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.excel.exception.ExcelPluginException;
import org.opsli.plugins.excel.listener.BatchExcelListener;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
@ -61,10 +66,11 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
@ -77,14 +83,8 @@ import java.util.function.Function;
@RestController
public abstract class BaseRestController <T extends BaseEntity, E extends ApiWrapper, S extends CrudServiceInterface<T,E>>{
/** 开启热点数据状态 */
protected boolean hotDataFlag = false;
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */
protected Class<E> modelClazz;
/** 凭证 10分钟失效 */
private static final int CERTIFICATE_EXPIRED_MINUTE = 10;
/** 配置类 */
@Autowired
@ -94,6 +94,10 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
@Autowired(required = false)
protected S IService;
/** Redis 类 */
@Autowired
private RedisPlugin redisPlugin;
/**
*
* id
@ -103,15 +107,18 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
*/
@ModelAttribute
public E get(@RequestParam(required=false) String id) {
if(StrUtil.isEmpty(id)){
return null;
}
return IService.get(id);
}
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
protected ResultVo<?> importExcel(MultipartHttpServletRequest request){
protected ResultWrapper<?> importExcel(MultipartHttpServletRequest request){
// 计时器
TimeInterval timer = DateUtil.timer();
Iterator<String> itr = request.getFileNames();
@ -119,21 +126,20 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
List<MultipartFile> files = request.getFiles(uploadedFile);
if (CollectionUtils.isEmpty(files)) {
// 请选择文件
return ResultVo.error(CoreMsg.EXCEL_FILE_NULL.getCode(),
CoreMsg.EXCEL_FILE_NULL.getMessage());
return ResultWrapper.getCustomResultWrapper(CoreMsg.EXCEL_FILE_NULL);
}
ResultVo<?> resultVo ;
ResultWrapper<?> resultVo ;
String msgInfo;
try {
UserModel user = UserUtil.getUser();
Date currDate = DateUtil.date();
// 导入优化为 监听器 模式 超过一定阈值直接释放资源 防止导入数据导致系统 OOM
ExcelUtil.getInstance().readExcelByListener(files.get(0), modelClazz, new BatchExcelListener<E>() {
ExcelUtil.getInstance().readExcelByListener(files.get(0), IService.getModelClass(), new BatchExcelListener<E>() {
@Override
public void saveData(List<E> dataList) {
// 处理字典数据
List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, modelClazz, ExcelOperate.READ);
List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, IService.getModelClass(), ExcelOperate.READ);
// 手动赋值 必要数据 防止频繁开启Redis网络IO
for (E model : disposeData) {
model.setIzManual(true);
@ -152,7 +158,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_SUCCESS.getMessage(), DateUtil.formatBetween(timerCount));
// 导出成功
resultVo = ResultVo.success(msgInfo);
resultVo = ResultWrapper.getSuccessResultWrapper(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_IMPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) {
@ -162,7 +168,8 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount),
e.getMessage());
// 导入失败
resultVo = ResultVo.error(CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo);
resultVo = ResultWrapper.getCustomResultWrapper(
CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo);
}
// 记录导出日志
log.info(msgInfo);
@ -170,108 +177,113 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
}
/**
*
* @param fileName
* @param response response
* Excel
*
* @param type ExcelExcel
* @param subName
* @param request request
* @return Optional<String>
*/
protected void importTemplate(String fileName, HttpServletResponse response, Method method){
this.excelExport(fileName + " 模版 ",null, response, method);
protected Optional<String> excelExportAuth(String type, String subName, HttpServletRequest request){
// 封装缓存数据
ExcelExportCache exportCache;
if(ExcelExportCache.EXCEL_EXPORT.equals(type)){
// 异常检测
QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), request.getParameterMap());
QueryWrapper<T> queryWrapper = queryBuilder.build();
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
long count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName)
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else if(ExcelExportCache.EXCEL_IMPORT_TEMPLATE_EXPORT.equals(type)){
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName+ " 模版 ")
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else {
return Optional.empty();
}
// 缓存Key
Long increment = redisPlugin
.increment(CacheUtil.formatKey(RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NUM_NAME));
String certificate = UniqueStrGeneratorUtils.generator(increment);
// 缓存Key
String certificateCacheKeyTmp = CacheUtil.formatKey(
RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
redisPlugin.put(certificateCacheKeyTmp, exportCache, CERTIFICATE_EXPIRED_MINUTE, TimeUnit.MINUTES);
return Optional.of(certificate);
}
/**
*
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param fileName
* @param queryWrapper
* @param response response
*/
protected void excelExport(String fileName, QueryWrapper<T> queryWrapper, HttpServletResponse response,
Method method){
// 权限认证
try {
if(method == null){
// 无权访问该方法
throw new TokenException(TokenMsg.EXCEPTION_NOT_AUTH);
protected void excelExport(String certificate, HttpServletResponse response){
// 缓存Key
String certificateCacheKeyTmp = CacheUtil.formatKey(
RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
Object cacheObj = redisPlugin.get(certificateCacheKeyTmp);
ExcelExportCache cache = Convert.convert(ExcelExportCache.class, cacheObj);
if(cache == null){
return;
}
}
// 主题名称
String subName = cache.getSubName();
// Token 认证
JwtRealm.authToken();
List<E> modelList = null;
RequiresPermissionsCus permissionsCus = method.getAnnotation(RequiresPermissionsCus.class);
if(permissionsCus != null){
// 方法权限认证
JwtRealm.authPerms(permissionsCus.value());
}
}catch (TokenException e){
// 推送错误信息
OutputStreamUtil.exceptionResponse(e.getMessage(), response);
return;
}
// 如果导出Excel 需要查询数据
if(ExcelExportCache.EXCEL_EXPORT.equals(cache.getType())){
// 参数Map
Map<String, String[]> parameterMap = new HashMap<>();
JSONObject jsonObject = JSONUtil.parseObj(cache.getParameterMapStr());
jsonObject.forEach((k, v) -> {
JSONArray values = (JSONArray) v;
String[] parameters = (String[]) values.toArray(String.class);
parameterMap.put(k, parameters);
});
// 计时器
TimeInterval timer = DateUtil.timer();
String msgInfo;
ResultVo<?> resultVo;
List<E> modelList = Lists.newArrayList();
try {
if(queryWrapper != null){
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
int count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), parameterMap);
QueryWrapper<T> queryWrapper = queryBuilder.build();
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, IService.getModelClass());
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, modelClazz);
}
// 导出Excel
ExcelUtil.getInstance().writeExcel(response, modelList ,fileName,"sheet", modelClazz ,ExcelTypeEnum.XLSX);
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_SUCCESS.getMessage(), modelList.size(),
DateUtil.formatBetween(timerCount));
// 导出成功
resultVo = ResultVo.success(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_EXPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) {
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount), e.getMessage());
// 导出失败
resultVo = ResultVo.error(CoreMsg.EXCEL_EXPORT_ERROR.getCode(), msgInfo);
}finally {
// 清空list
modelList.clear();
}
// 记录导出日志
log.info(msgInfo);
// 导出异常
if(!resultVo.isSuccess()){
// 无权访问该方法
OutputStreamUtil.exceptionResponse(resultVo.getMsg(), response);
}
// 导出Excel
ExcelUtil.getInstance().writeExcel(
response, modelList, subName,"sheet", IService.getModelClass() ,ExcelTypeEnum.XLSX);
// 删除凭证
redisPlugin.del(certificateCacheKeyTmp);
}
/**
*
*/
@ -347,34 +359,28 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// =================================================
@PostConstruct
public void init(){
try {
this.modelClazz = IService.getModelClazz();
this.entityClazz = IService.getEntityClazz();
if(IService != null){
// 判断Service 是否包含 热数据注解
this.hotDataFlag = AnnotationUtil.hasAnnotation(IService.getServiceClazz(),
EnableHotData.class);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class ExcelExportCache implements Serializable {
/**
*
* @return E
*/
private E createModel() {
try {
Class<E> modelClazz = this.modelClazz;
return modelClazz.newInstance();
} catch (Exception e) {
log.error(e.getMessage(),e);
}
return null;
}
private static final long serialVersionUID = 1L;
public final static String EXCEL_IMPORT_TEMPLATE_EXPORT = "import-template-export";
public final static String EXCEL_EXPORT = "export";
/** 主题名 */
private String subName;
/** 类型 */
private String type;
/** 请求参数Map */
private String parameterMapStr;
}
}

@ -0,0 +1,62 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.base.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021122216:22:37
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginUserDto implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户名 */
private String username;
/** 用户昵称 */
private String nickname;
/** 租户ID */
private String tenantId;
/** 手机 */
private String mobile;
/** 邮箱 */
private String email;
/** 登录来源: 0:PC端1:APP-安卓 2:APP-IOS 3:小程序 */
private String loginFrom;
/** 登录ip */
private String loginIp;
}

@ -16,10 +16,14 @@
package org.opsli.core.base.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.reflect.SpringReflectionHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
@ -35,6 +39,7 @@ import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.chain.QueryDataPermsHandler;
import org.opsli.core.persistence.querybuilder.chain.QueryTenantHandler;
import org.opsli.core.persistence.querybuilder.conf.WebQueryConf;
import org.springframework.core.GenericTypeResolver;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
@ -64,12 +69,8 @@ import java.util.Map;
public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEntity, E extends ApiWrapper>
extends BaseService<M, T> implements CrudServiceInterface<T,E> {
/** JSON tmp */
private static final String JSON_TMP = "{\"id\":\"1\"}";
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */
protected Class<E> modelClazz;
protected Class<E> modelClazz = getInnerModelClazz();
@Override
public E get(String id) {
@ -213,7 +214,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public List<T> findList(QueryWrapper<T> queryWrapper) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, queryWrapper);
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), queryWrapper);
return super.list(qWrapper);
}
@ -221,7 +222,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public List<T> findAllList() {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz);
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass());
return super.list(qWrapper);
}
@ -229,7 +230,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public Page<T,E> findPage(Page<T,E> page) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper());
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin();
try{
List<T> list = super.list(qWrapper);
@ -245,7 +246,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public Page<T,E> findPageNotCount(Page<T,E> page) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper());
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin(false);
try{
List<T> list = super.list(qWrapper);
@ -286,7 +287,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return T
*/
protected T transformM2T(E model){
return WrapperUtil.transformInstance(model, entityClazz);
return WrapperUtil.transformInstance(model, this.getEntityClass());
}
/**
@ -296,7 +297,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return List<T>
*/
protected List<T> transformMs2Ts(List<E> models){
return WrapperUtil.transformInstance(models, entityClazz);
return WrapperUtil.transformInstance(models, this.getEntityClass());
}
/**
@ -342,26 +343,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
// ======================== 初始化 ========================
/**
*
*/
@PostConstruct
public void init(){
try {
this.modelClazz = this.getInnerModelClazz();
this.entityClazz = this.getInnerEntityClazz();
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Override
public Class<T> getEntityClazz() {
return entityClazz;
}
@Override
public Class<E> getModelClazz() {
public Class<E> getModelClass() {
return modelClazz;
}
@ -371,56 +354,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
*/
@SuppressWarnings("unchecked")
public Class<E> getInnerModelClazz(){
String typeName = "E";
Class<E> tClass = null;
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<E>) entryValue;
break;
}
}
}
}
return tClass;
}
/**
* Entity Clazz
* @return Class<T>
*/
@SuppressWarnings("unchecked")
private Class<T> getInnerEntityClazz(){
String typeName = "T";
Class<T> tClass = null;
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<T>) entryValue;
break;
}
}
}
}
return tClass;
Class<?>[] typeArguments = GenericTypeResolver.resolveTypeArguments(this.getClass(), CrudServiceImpl.class);
return null == typeArguments ? null : (Class<E>) typeArguments[2];
}
}

@ -44,6 +44,13 @@ import java.util.List;
public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper> extends BaseServiceInterface<T> {
/**
* Model Class
* @return Class<E>
*/
Class<E> getModelClass();
/**
*
*
@ -201,19 +208,7 @@ public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper
* @return Page<T>
*/
Page<T,E> findPageNotCount(Page<T,E> page);
/**
* Model Clazz
* @return Class
*/
Class<E> getModelClazz();
/**
* Entity Clazz
* @return Class
*/
Class<T> getEntityClazz();
}

@ -25,7 +25,9 @@ import com.google.common.util.concurrent.Striped;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@ -37,6 +39,8 @@ import java.util.function.Function;
* 使
*
* Redis String Hash
*
* RedisTemplate LRU cache 穿 N
*
* @author Parker
* @date 2021/12/10 12:39
@ -373,6 +377,10 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回
@ -387,6 +395,11 @@ public final class SecurityCache {
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回
@ -588,48 +601,28 @@ public final class SecurityCache {
/**
*
*
* @param redisTemplate redisTemplate
* @param keys
*/
public static boolean removeMore(
public static boolean remove(
final RedisTemplate<String, Object> redisTemplate,
final String... keys) {
if (null == redisTemplate || null == keys) {
throw new RuntimeException("入参[redisTemplate,keys]必填");
throw new RuntimeException("入参[redisTemplate,key]必填");
}
int count = keys.length;
List<String> removeKeyList = new ArrayList<>();
for (String key : keys) {
boolean isRemove = remove(redisTemplate, key);
if(isRemove){
count--;
}
}
return 0 == count;
}
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
/**
*
* @param redisTemplate redisTemplate
* @param key
*/
public static boolean remove(
final RedisTemplate<String, Object> redisTemplate,
final String key) {
if (null == redisTemplate || null == key) {
throw new RuntimeException("入参[redisTemplate,key]必填");
removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV));
removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH));
}
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
String cacheKeyByKv = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 清除缓存
redisTemplate.delete(cacheKeyByKv);
redisTemplate.delete(cacheKeyByHash);
redisTemplate.delete(removeKeyList);
return true;
}

@ -0,0 +1,43 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* EventBus Spring
*
* @author Parker
* @date 202112710:39:16
*/
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.scanConsumer(null);
}
@Override
public void scanConsumer(String packageName) {
context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
this.addConsumer(v);
});
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
/**
* EventBus
*
* @author Parker
* @date 202112710:38:24
*/
public interface IEventBus {
/**
*
* @param event
*/
void post(Object event);
/**
*
* @param obj classkey
*/
void addConsumer(Object obj);
/**
*
* @param obj classkey
*/
void removeConsumer(Object obj);
/**
*
* @param packageName
*/
void scanConsumer(String packageName);
}

@ -1,5 +1,5 @@
/**
* Copyright 2018 http://www.renren.io
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@ -13,22 +13,20 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.shiro.utils;
package org.opsli.core.eventbus;
/**
* RedisKeys
* EventBus
*
* @author Mark sunlightcs@gmail.com
* @since 3.0.0 2017-07-18
* @author Parker
* @date 2020/9/25 12:19
*/
public class RedisKeys {
public interface IEventConsumer<T> {
public static String getSysConfigKey(String key){
return "system:config:" + key;
}
/**
*
* @param event
*/
void consumer(T event);
public static String getShiroSessionKey(String key){
return "sessionid:" + key;
}
}

@ -43,7 +43,7 @@ import static org.opsli.common.constants.OrderConstants.LIMITER_AOP_SORT;
/**
*
*
* @author
* @author Parker
* @date 2020-09-16
*/
@Slf4j

@ -1,75 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.opsli.core.utils.LogUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import static org.opsli.common.constants.OrderConstants.TOKEN_AOP_SORT;
/**
*
*
* @author parker
* @date 2020-09-16
*/
@Slf4j
@Order(TOKEN_AOP_SORT)
@Aspect
@Component
public class LogAop {
@Pointcut("execution(public * org.opsli..*.*Controller*.*(..))")
public void requestMapping() {
}
/**
* post
* @param point point
*/
@Around("requestMapping()")
public Object tokenAop(ProceedingJoinPoint point) throws Throwable {
// 计时器
TimeInterval timer = DateUtil.timer();
// 执行
Exception exception = null;
// 防止线程抛异常 线程变量不回收 导致oom
Object returnValue;
try {
// 执行正常操作
returnValue = point.proceed();
}catch (Exception e){
exception = e;
throw e;
} finally {
// 花费毫秒数
long timerCount = timer.interval();
//保存日志
LogUtil.saveLog(point, exception, timerCount);
}
return returnValue;
}
}

@ -1,190 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.CryptoPlugin;
import opsli.plugins.crypto.enums.CryptoSymmetricType;
import opsli.plugins.crypto.model.CryptoAsymmetric;
import opsli.plugins.crypto.model.CryptoSymmetric;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import opsli.plugins.crypto.strategy.CryptoSymmetricService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.api.base.encrypt.BaseEncrypt;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.LoginCrypto;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.options.CryptoConfigFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import static org.opsli.common.constants.OrderConstants.ENCRYPT_ADN_DECRYPT_AOP_SORT;
/**
*
*
* @author parker
* @date 2021-01-23
*/
@Slf4j
@Order(ENCRYPT_ADN_DECRYPT_AOP_SORT)
@Aspect
@Component
public class LoginCryptoAop {
@Pointcut("@annotation(org.opsli.common.annotation.LoginCrypto)")
public void encryptAndDecrypt() {
}
/**
* post
* @param point point
*/
@Around("encryptAndDecrypt()")
public Object encryptAndDecryptHandle(ProceedingJoinPoint point) throws Throwable {
// 获得请求参数
Object[] args = point.getArgs();
// 返回结果
Object returnValue;
MethodSignature signature = (MethodSignature) point.getSignature();
// 获得 方法
Method method = signature.getMethod();
// 获得方法注解
LoginCrypto annotation =
method.getAnnotation(LoginCrypto.class);
// 获得非对称加解密 执行器
CryptoAsymmetricService asymmetric = null;
// 非对称加解密模型
CryptoAsymmetric cryptoAsymmetric = null;
if(annotation != null && annotation.enable()){
asymmetric = CryptoPlugin.getAsymmetric();
cryptoAsymmetric = CryptoConfigFactory.INSTANCE.getCryptoAsymmetric();
}
// 1. 请求解密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
enterDecrypt(args, method, asymmetric, cryptoAsymmetric);
}
}
// 2. 执行方法
returnValue = point.proceed(args);
// 3. 返回加密 返回加密为对称加密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
CryptoSymmetricService symmetric = CryptoPlugin.getSymmetric();
CryptoSymmetric symmetricModel = symmetric.createNilModel();
symmetricModel.setCryptoType(CryptoSymmetricType.DES);
symmetricModel.setPrivateKey(cryptoAsymmetric.getPublicKey());
// 执行加密操作
returnValue = resultEncrypt(returnValue, symmetric, symmetricModel);
}
}
return returnValue;
}
/**
*
* @param args
* @param method
* @param asymmetric
* @param cryptoModel
*/
private void enterDecrypt(Object[] args, Method method, CryptoAsymmetricService asymmetric, CryptoAsymmetric cryptoModel) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
// 参数校验
if(arg instanceof BaseEncrypt){
// 获得加密数据
BaseEncrypt baseEncrypt = (BaseEncrypt) arg;
String encryptData = baseEncrypt.getEncryptData();
// 解密对象
Object dataToObj = asymmetric.decryptToObj(cryptoModel, encryptData);
// 根据方法类型转化对象
Type type = TypeUtil.getParamType(method, i);
Object obj = Convert.convert(type, dataToObj);
// 修改缓存中设备数据 空值不覆盖
Map<String, Object> modelBeanMap = BeanUtil.beanToMap(obj);
modelBeanMap.entrySet().removeIf(entry -> entry.getValue() == null);
// 反射赋值
Field[] fields = ReflectUtil.getFields(arg.getClass());
for (Field f : fields) {
Object val = modelBeanMap.get(f.getName());
if(val == null){
continue;
}
//根据需要,将相关属性赋上默认值
BeanUtil.setProperty(arg, f.getName(), val);
}
}
}
}
/**
*
* @param returnValue
* @param symmetric
* @param cryptoModel
* @return Object
*/
@SuppressWarnings("unchecked")
private Object resultEncrypt(Object returnValue, CryptoSymmetricService symmetric, CryptoSymmetric cryptoModel) {
if(returnValue != null){
try {
// 执行加密过程
if(returnValue instanceof ResultVo){
// 重新赋值 data
ResultVo<Object> ret = (ResultVo<Object>) returnValue;
ret.setData(
symmetric.encrypt(cryptoModel, ret.getData())
);
}else {
returnValue = symmetric.encrypt(cryptoModel, returnValue);
}
}catch (Exception e){
// 非对称加密失败
throw new ServiceException(CoreMsg.OTHER_EXCEPTION_CRYPTO_EN);
}
}
return returnValue;
}
}

@ -38,7 +38,7 @@ import static org.opsli.common.constants.OrderConstants.SEARCH_HIS_AOP_SORT;
/**
* AOP
*
* @author
* @author Parker
* @date 2020-09-16
*/
@Slf4j

@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* , jwt token
*
* @author
* @author Parker
* @date 2021122216:35:20
*/
@Slf4j

@ -18,14 +18,9 @@ package org.opsli.core.handler;
import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationException;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.common.exception.*;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@ -86,9 +81,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> businessException(ServiceException e) {
public ResultWrapper<?> businessException(ServiceException e) {
log.warn("业务异常 - 异常编号:{} - 异常信息:{}",e.getCode(),e.getMessage());
return ResultVo.error(e.getCode(), e.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -97,8 +92,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(EmptyException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> emptyException(EmptyException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> emptyException(EmptyException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -107,68 +102,19 @@ public class GlobalExceptionHandler {
@ExceptionHandler(JwtException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> jwtException(JwtException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> jwtException(JwtException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(IncorrectCredentialsException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public ResultVo<?> incorrectCredentialsException(IncorrectCredentialsException e) {
// token失效请重新登录
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(LockedAccountException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> lockedAccountException(LockedAccountException e) {
// 账号已被锁定,请联系管理员
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(AuthorizationException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> authorizationException(AuthorizationException e) {
// 无权访问该方法
return ResultVo.error(TokenMsg.EXCEPTION_NOT_AUTH.getCode(),
TokenMsg.EXCEPTION_NOT_AUTH.getMessage()
);
}
/**
* Shiro
*/
@ExceptionHandler(UnsupportedTokenException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> unsupportedTokenException(UnsupportedTokenException e) {
// 找不到认证授权器
return ResultVo.error(TokenMsg.EXCEPTION_NOT_REALM.getCode(),
TokenMsg.EXCEPTION_NOT_REALM.getMessage()
);
}
/**
* Token
*/
@ExceptionHandler(TokenException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> tokenException(TokenException e) {
public ResultWrapper<?> tokenException(TokenException e) {
// Token 异常
return ResultVo.error(e.getCode(), e.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -177,8 +123,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(WafException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ResultVo<?> wafException(WafException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> wafException(WafException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
// ============================
@ -189,9 +135,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> nullPointerException(NullPointerException e) {
public ResultWrapper<?> nullPointerException(NullPointerException e) {
log.error("空指针异常:{}",e.getMessage(),e);
return ResultVo.error(e.getMessage());
return ResultWrapper.getErrorResultWrapper();
}
@ -201,9 +147,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> sqlIntegrityConstraintViolationException(EmptyException e) {
public ResultWrapper<?> sqlIntegrityConstraintViolationException(EmptyException e) {
log.error("数据异常:{}",e.getMessage(),e);
return ResultVo.error(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
}
/**
@ -212,17 +158,17 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> sqlException(SQLException e) {
public ResultWrapper<?> sqlException(SQLException e) {
//log.error("数据异常:{}",e.getMessage(),e);
// 默认值异常
if(StringUtils.contains(e.getMessage(),SQL_EXCEPTION)){
String field = e.getMessage().replaceAll("Field '","")
.replaceAll("' doesn't have a default value","");
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getMessage(), field);
return ResultVo.error(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
}
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_UNKNOWN.getMessage(), e.getMessage());
return ResultVo.error(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
}
}

@ -28,7 +28,7 @@ import java.util.Optional;
/**
*
*
* @author
* @author Parker
* @date 2021122216:22:59
*/
public final class UserContextHolder {

@ -0,0 +1,84 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.annotation;
import org.opsli.core.log.enums.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Target({ElementType.METHOD}) //注解作用于方法级别
@Retention(RetentionPolicy.RUNTIME) //运行时起作用
public @interface OperateLogger {
/**
*
*/
boolean loggable() default true;
/**
*
* 使: ${tel}
*/
String description() default "";
/**
*
*/
ModuleEnum module() default ModuleEnum.MODULE_COMMON;
/**
* (enum): select,insert,update,delete
*/
OperationTypeEnum operationType() default OperationTypeEnum.UNKNOWN;
/**
*
*/
LogTypeEnum type() default LogTypeEnum.BACKEND;
/**
*
*/
LogLevelEnum level() default LogLevelEnum.INFO;
/**
* ,
* ALL-, BEFORE-, AFTER-
*/
LogScopeEnum scope() default LogScopeEnum.ALL;
/**
*
*/
boolean db() default false;
/**
*
*/
boolean console() default true;
}

@ -0,0 +1,220 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.aspect;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.common.utils.MessUtil;
import org.opsli.core.base.dto.LoginUserDto;
import org.opsli.core.holder.UserContextHolder;
import org.opsli.core.log.annotation.OperateLogger;
import org.opsli.core.log.bean.OperationLog;
import org.opsli.core.log.bus.OperationLogEventBus;
import org.opsli.core.log.enums.LogLevelEnum;
import org.opsli.core.log.enums.LogScopeEnum;
import org.opsli.core.utils.UserTokenUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Slf4j
@Aspect
@Component
@Order(50)
public class OperateLogAspect {
/** 替换条件 */
private static final String RE = "\\$\\{([\\w\\.\\-\\/\\+\\$\\#\\@\\!\\^\\&\\(\\)]+)\\}";
@Resource
private OperationLogEventBus operationLogEventBus;
@Pointcut("@annotation(org.opsli.core.log.annotation.OperateLogger)")
public void operationLog(){}
/**
* MethodInterceptor
*/
@Around("operationLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
long time = System.currentTimeMillis();
try {
result = joinPoint.proceed();
return result;
} finally {
time = System.currentTimeMillis() - time;
try {
// 方法执行完成后增加日志
addOperationLog(joinPoint, result, time);
}catch (Exception e){
log.error("LogAspect 操作失败:{}" + e.getMessage());
e.printStackTrace();
}
}
}
/**
*
* @param joinPoint point
* @param result
* @param time
*/
private void addOperationLog(JoinPoint joinPoint, Object result, long time){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
OperateLogger annotation = signature.getMethod()
.getAnnotation(OperateLogger.class);
if(annotation == null || !annotation.loggable()){
return;
}
OperationLog operationLog = new OperationLog();
// 参数
String argsStr = null;
try {
argsStr = JSONUtil.toJsonStr(joinPoint.getArgs());
}catch (Exception ignored){}
// 结果
String resultStr = null;
try {
resultStr = JSONUtil.toJsonStr(result);
}catch (Exception ignored){}
if(LogScopeEnum.REQUEST.equals(annotation.scope())){
operationLog.setArgs(argsStr);
} else if(LogScopeEnum.RESPONSE.equals(annotation.scope())){
operationLog.setReturnValue(resultStr);
} else if(LogScopeEnum.ALL.equals(annotation.scope())){
operationLog.setArgs(argsStr);
operationLog.setReturnValue(resultStr);
}
operationLog.setId(UUID.randomUUID().toString());
operationLog.setRunTime(time);
operationLog.setCreateTime(System.currentTimeMillis());
operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
operationLog.setLevel(annotation.level().getValue());
operationLog.setDescription(
// 对当前登录用户和占位符处理
getDetail(
((MethodSignature) joinPoint.getSignature()).getParameterNames(),
joinPoint.getArgs(),
annotation)
);
operationLog.setOperationType(annotation.operationType().getValue());
operationLog.setLogType(annotation.type().getValue());
operationLog.setModuleId(annotation.module().getId());
// 当前Token
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
operationLog.setUserId(String.valueOf(loginUserDto.getUid()));
operationLog.setUsername(loginUserDto.getUsername());
operationLog.setRealName(loginUserDto.getNickname());
operationLog.setTenantId(loginUserDto.getTenantId());
}
}
// 输出控制台
if(annotation.console()){
printToConsole(annotation.level(), operationLog);
}
// 存入数据库
if(annotation.db()){
operationLogEventBus.post(operationLog);
}
}
/**
*
* @param level
* @param operationLog
*/
private void printToConsole(LogLevelEnum level, OperationLog operationLog){
switch (level){
case INFO:
log.info("记录日志:{}" , operationLog);
break;
case DEBUG:
log.debug("记录日志:{}" , operationLog);
break;
case WARN:
log.warn("记录日志:{}" , operationLog);
break;
case ERROR:
log.error("记录日志:{}" , operationLog);
break;
case TRACE:
log.trace("记录日志:{}" , operationLog);
break;
default:
break;
}
}
/**
*
* @param argNames
* @param args
* @param annotation
* @return
*/
private String getDetail(String[] argNames, Object[] args, OperateLogger annotation){
Map<String, Object> map = Maps.newHashMap();
for(int i = 0;i < argNames.length;i++){
map.put(argNames[i], args[i]);
}
String description = annotation.description();
try {
// 当前用户信息
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
description = "'" + loginUserDto.getNickname() + "'=> " + annotation.description();
}
}
description = MessUtil.getMes(description, RE, "${", "}", map);
}catch (Exception e){
e.printStackTrace();
}
return description;
}
}

@ -0,0 +1,82 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bean;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Data
@ToString
public class OperationLog implements Serializable {
private static final long serialVersionUID = 1L;
/** 日志ID */
private String id;
/** 创建时间 */
private long createTime;
/** 日志等级 */
private String level;
/** 被操作的系统模块 */
private String moduleId;
/** 方法名 */
private String method;
/** 参数 */
private String args;
/** 操作人id */
private String userId;
/** 操作人用户名 */
private String username;
/** 真实姓名 */
private String realName;
/** 日志描述 */
private String description;
/** 操作类型 */
private String operationType;
/** 方法运行时间 */
private Long runTime;
/** 方法返回值 */
private String returnValue;
/** 租户ID */
private String tenantId;
/**
*
*/
private String logType;
}

@ -0,0 +1,72 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bus;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.thread.ThreadPoolFactory;
import org.opsli.core.eventbus.AbstractSpringEventBus;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线
* @author
* @date 202112710:42:39
*/
@Component
@Slf4j
public class OperationLogEventBus extends AbstractSpringEventBus implements SubscriberExceptionHandler {
private final EventBus eventBus;
public OperationLogEventBus() {
// 异步事件配置线程池
eventBus = new AsyncEventBus(
ThreadPoolFactory.createInitThreadPool(5, 10, 60, TimeUnit.SECONDS,
1024, "Operation-Log-Event-Bus",
new ThreadPoolExecutor.CallerRunsPolicy()
)
, this
);
}
@Override
public void post(Object event) {
eventBus.post(event);
}
@Override
public void addConsumer(Object obj) {
eventBus.register(obj);
}
@Override
public void removeConsumer(Object obj) {
eventBus.unregister(obj);
}
@Override
public void handleException(Throwable exception, SubscriberExceptionContext context) {
log.error("user event handler exception", exception);
}
}

@ -13,23 +13,29 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
package org.opsli.core.log.enums;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
*
* @author Parker
* @date 2020-09-22 17:07
* @date 202171520:28:24
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissionsCus {
@Getter
@AllArgsConstructor
public enum LogLevelEnum {
String[] value();
/**
*
*/
DEBUG("-1"),
INFO("0"),
WARN("1"),
ERROR("2"),
TRACE("3");
private final String value;
}

@ -13,25 +13,31 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
import java.lang.annotation.*;
package org.opsli.core.log.enums;
/**
*
*
*
*
*
* @author Parker
* @date 202151814:46:02
* @date 202171520:28:24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginCrypto {
public enum LogScopeEnum {
/**
*
*/
ALL(0),
REQUEST(1),
RESPONSE(2)
;
private final int value;
/** 加密启用状态 */
boolean enable() default true;
public int getValue() {
return value;
}
LogScopeEnum(int value) {
this.value = value;
}
}

@ -13,25 +13,36 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
package org.opsli.core.log.enums;
/**
*
* @author parker
* @date 2020-09-12
*
*
* @author Parker
* @date 202171520:28:24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableLog {
public enum LogTypeEnum {
/** WEB */
WEB("0"),
/** 客户端 */
CLIENT("1"),
/** 后端 */
BACKEND("2"),
/** 程序自动 */
AUTO("3")
;
private final String value;
/** 标题 */
String title() default "";
public String getValue() {
return value;
}
LogTypeEnum(String value) {
this.value = value;
}
}

@ -0,0 +1,66 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:19:27
*/
public enum ModuleEnum {
/** 模块 */
MODULE_UNKNOWN("-1", "未知(请配置模块)"),
MODULE_COMMON("00", "公共模块"),
MODULE_USER("01", "用户模块"),
MODULE_ROLE("02", "角色模块"),
MODULE_MENU("03", "菜单模块"),
MODULE_ORG("04", "组织模块"),
MODULE_DICT("05", "字典模块"),
MODULE_TENANT("06", "租户模块"),
MODULE_AREA("07", "地区模块"),
MODULE_MONITOR("08", "监控模块"),
MODULE_GENERATOR("09", "代码生成器"),
MODULE_OPERATION("11", "行为日志"),
MODULE_TEST("100", "测试模块"),
MODULE_TEST_USER("101", "测试用户模块"),
MODULE_TEST_CAR("102", "测试汽车模块"),
;
private final String id;
private final String name;
ModuleEnum(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:27:27
*/
public enum OperationTypeEnum {
/**
*
*/
UNKNOWN("unknown"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert");
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
OperationTypeEnum(String s) {
this.value = s;
}
}

@ -30,14 +30,20 @@ public enum TokenMsg implements BaseMsg {
*/
EXCEPTION_TOKEN_CREATE_ERROR(12000,"生成Token失败"),
EXCEPTION_TOKEN_CREATE_LIMIT_ERROR(12001,"您的账号已在其他设备登录"),
EXCEPTION_TOKEN_LOSE_EFFICACY(401,"Token失效请重新登录"),
EXCEPTION_TOKEN_LOSE_EFFICACY(401,"凭证已过期,请重新登陆"),
AUTH_CREDENTIALS_INVALID(100208, "凭证已过期,请重新登陆"),
AUTH_AUTH_INVALID(100209, "认证失败,请重新登陆"),
/**
*
*/
EXCEPTION_CAPTCHA_CERTIFICATE_ERROR(12097, "凭证验证失败,请刷新重试"),
EXCEPTION_CAPTCHA_ARGS_NULL(12098, "参数异常"),
EXCEPTION_CAPTCHA_OFTEN(12099, "已获取验证码,请勿频繁获取"),
EXCEPTION_CAPTCHA_ERROR(12100,"验证码不正确!"),
EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效"),
EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效, 请重新生成"),
EXCEPTION_CAPTCHA_UUID_NULL(12202, "验证码UUID为空"),
EXCEPTION_CAPTCHA_CODE_NULL(12203, "验证码为空"),
EXCEPTION_LOGIN_ACCOUNT_NO(12101,"账号或密码不正确!"),

@ -0,0 +1,81 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.filter;
import lombok.AllArgsConstructor;
import org.opsli.core.base.dto.LoginUserDto;
import org.opsli.core.security.service.UidUserDetailDetailServiceImpl;
import org.opsli.core.utils.UserTokenUtil;
import org.opsli.plugins.security.authentication.AfterAuthenticationToken;
import org.opsli.plugins.security.exception.AuthException;
import org.opsli.plugins.security.exception.errorcode.AuthErrorCodeEnum;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* JWT
* filter Spring
* @author Parker
* @date 2022072216:16:42
*/
@AllArgsConstructor
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private final UidUserDetailDetailServiceImpl uidUserDetailDetailService;
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 获取token
String token = UserTokenUtil.getRequestToken(request);
if (!StringUtils.hasText(token)) {
//放行
filterChain.doFilter(request, response);
return;
}
// 验证Token
UserTokenUtil.verify(token);
// 获得登陆用户信息
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(token)
// 认证无效
.orElseThrow(() -> new AuthException(AuthErrorCodeEnum.AUTH_AUTH_INVALID));
// 这里用Uid 获取用户信息,因为涉及到超管切换租户身份
// 非 租户系统 可以直接使用 用户名获取信息
UserDetails userDetails = uidUserDetailDetailService.loadUserByPrincipal(loginUserDto.getUid())
// 认证无效
.orElseThrow(() -> new AuthException(AuthErrorCodeEnum.AUTH_AUTH_INVALID));
AfterAuthenticationToken authenticationToken =
new AfterAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//放行
filterChain.doFilter(request, response);
}
}

@ -0,0 +1,108 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.service;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.enums.DictType;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.security.UserDetailModel;
import org.opsli.plugins.security.authentication.EmailCodeAuthenticationToken;
import org.opsli.plugins.security.authentication.EmailPasswordAuthenticationToken;
import org.opsli.plugins.security.properties.AuthProperties;
import org.opsli.plugins.security.service.ILoadUserDetailService;
import org.opsli.plugins.security.utils.PasswordUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;
/**
* + Service
*
*
* @author Parker
* @date 2022-07-14 4:44 PM
**/
@AllArgsConstructor
@Service
public class EmailUserDetailDetailServiceImpl implements ILoadUserDetailService {
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
private final AuthProperties authProperties;
@Override
public Collection<Class<? extends Authentication>> getClassTypes() {
List<Class<? extends Authentication>> classes = new ArrayList<>();
classes.add(EmailCodeAuthenticationToken.class);
classes.add(EmailPasswordAuthenticationToken.class);
return classes;
}
@Override
public Optional<UserDetails> loadUserByPrincipal(Object principal) {
UserModel userModel = UserUtil.getUserByEmail((String) principal);
if(null == userModel){
return Optional.empty();
}
// 处理权限数据
List<String> authorities = new ArrayList<>();
List<String> userRoles = UserUtil.getUserRolesByUserId(userModel.getId());
List<String> userAllPerms = UserUtil.getUserAllPermsByUserId(userModel.getId());
for (String userRole : userRoles) {
authorities.add(DEFAULT_ROLE_PREFIX+userRole);
}
authorities.addAll(userAllPerms);
// 清除空的 授权
authorities.removeIf(StrUtil::isEmpty);
List<GrantedAuthority> grantedAuthorities = authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
UserDetailModel userDetailModel = UserDetailModel.builder()
.username(userModel.getUsername())
.password(userModel.getPassword())
// 账户启动
.enabled(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未过期(如果需要 请自行扩展字段)
.accountNonExpired(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未锁定(如果需要 请自行扩展字段)
.accountNonLocked(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 判断凭证是否过期(默认不判断 如果需要 请自行扩展过期后修改密码操作)
.credentialsNonExpired(
PasswordUtil.isCredentialsNonExpired(
userModel.getPassword(), authProperties.getCredentialsExpired()))
// 授权信息
.authorities(grantedAuthorities)
.build();
return Optional.ofNullable(userDetailModel);
}
}

@ -0,0 +1,110 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.service;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.enums.DictType;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.security.UserDetailModel;
import org.opsli.plugins.security.authentication.MobileCodeAuthenticationToken;
import org.opsli.plugins.security.authentication.MobilePasswordAuthenticationToken;
import org.opsli.plugins.security.properties.AuthProperties;
import org.opsli.plugins.security.service.ILoadUserDetailService;
import org.opsli.plugins.security.utils.PasswordUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* + Service
*
*
* @author Parker
* @date 2022-07-14 4:44 PM
**/
@AllArgsConstructor
@Service
public class MobileUserDetailDetailServiceImpl implements ILoadUserDetailService {
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
private final AuthProperties authProperties;
@Override
public Collection<Class<? extends Authentication>> getClassTypes() {
List<Class<? extends Authentication>> classes = new ArrayList<>();
classes.add(MobileCodeAuthenticationToken.class);
classes.add(MobilePasswordAuthenticationToken.class);
return classes;
}
@Override
public Optional<UserDetails> loadUserByPrincipal(Object principal) {
UserModel userModel = UserUtil.getUserByMobile((String) principal);
if(null == userModel){
return Optional.empty();
}
// 处理权限数据
List<String> authorities = new ArrayList<>();
List<String> userRoles = UserUtil.getUserRolesByUserId(userModel.getId());
List<String> userAllPerms = UserUtil.getUserAllPermsByUserId(userModel.getId());
for (String userRole : userRoles) {
authorities.add(DEFAULT_ROLE_PREFIX+userRole);
}
authorities.addAll(userAllPerms);
// 清除空的 授权
authorities.removeIf(StrUtil::isEmpty);
List<GrantedAuthority> grantedAuthorities = authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
UserDetailModel userDetailModel = UserDetailModel.builder()
.username(userModel.getUsername())
.password(userModel.getPassword())
// 账户启动
.enabled(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未过期(如果需要 请自行扩展字段)
.accountNonExpired(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未锁定(如果需要 请自行扩展字段)
.accountNonLocked(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 判断凭证是否过期(默认不判断 如果需要 请自行扩展过期后修改密码操作)
.credentialsNonExpired(
PasswordUtil.isCredentialsNonExpired(
userModel.getPassword(), authProperties.getCredentialsExpired()))
// 授权信息
.authorities(grantedAuthorities)
.build();
return Optional.ofNullable(userDetailModel);
}
}

@ -0,0 +1,102 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.service;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.enums.DictType;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.security.UserDetailModel;
import org.opsli.plugins.security.properties.AuthProperties;
import org.opsli.plugins.security.service.ILoadUserDetailService;
import org.opsli.plugins.security.utils.PasswordUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* ID Service
*
* @author Parker
* @date 2022-07-14 4:44 PM
**/
@AllArgsConstructor
@Service("uidUserDetailDetailService")
public class UidUserDetailDetailServiceImpl implements ILoadUserDetailService {
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
private final AuthProperties authProperties;
@Override
public Collection<Class<? extends Authentication>> getClassTypes() {
// 为空则不会进入 Token 工厂内
return null;
}
@Override
public Optional<UserDetails> loadUserByPrincipal(Object principal) {
UserModel userModel = UserUtil.getUser((String) principal);
if(null == userModel){
return Optional.empty();
}
// 处理权限数据
List<String> authorities = new ArrayList<>();
List<String> userRoles = UserUtil.getUserRolesByUserId(userModel.getId());
List<String> userAllPerms = UserUtil.getUserAllPermsByUserId(userModel.getId());
for (String userRole : userRoles) {
authorities.add(DEFAULT_ROLE_PREFIX+userRole);
}
authorities.addAll(userAllPerms);
// 清除空的 授权
authorities.removeIf(StrUtil::isEmpty);
List<GrantedAuthority> grantedAuthorities = authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
UserDetailModel userDetailModel = UserDetailModel.builder()
.username(userModel.getUsername())
.password(userModel.getPassword())
// 账户启动
.enabled(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未过期(如果需要 请自行扩展字段)
.accountNonExpired(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未锁定(如果需要 请自行扩展字段)
.accountNonLocked(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 判断凭证是否过期(默认不判断 如果需要 请自行扩展过期后修改密码操作)
.credentialsNonExpired(
PasswordUtil.isCredentialsNonExpired(
userModel.getPassword(), authProperties.getCredentialsExpired()))
// 授权信息
.authorities(grantedAuthorities)
.build();
return Optional.ofNullable(userDetailModel);
}
}

@ -0,0 +1,102 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.service;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.enums.DictType;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.security.UserDetailModel;
import org.opsli.plugins.security.properties.AuthProperties;
import org.opsli.plugins.security.service.ILoadUserDetailService;
import org.opsli.plugins.security.utils.PasswordUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* + Service
*
*
* @author Parker
* @date 2022-07-14 4:44 PM
**/
@AllArgsConstructor
@Service("usernameUserDetailDetailService")
public class UsernameUserDetailDetailServiceImpl implements ILoadUserDetailService {
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
private final AuthProperties authProperties;
@Override
public Collection<Class<? extends Authentication>> getClassTypes() {
return Collections.singleton(UsernamePasswordAuthenticationToken.class);
}
@Override
public Optional<UserDetails> loadUserByPrincipal(Object principal) {
UserModel userModel = UserUtil.getUserByUserName((String) principal);
if(null == userModel){
return Optional.empty();
}
// 处理权限数据
List<String> authorities = new ArrayList<>();
List<String> userRoles = UserUtil.getUserRolesByUserId(userModel.getId());
List<String> userAllPerms = UserUtil.getUserAllPermsByUserId(userModel.getId());
for (String userRole : userRoles) {
authorities.add(DEFAULT_ROLE_PREFIX+userRole);
}
authorities.addAll(userAllPerms);
// 清除空的 授权
authorities.removeIf(StrUtil::isEmpty);
List<GrantedAuthority> grantedAuthorities = authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
UserDetailModel userDetailModel = UserDetailModel.builder()
.username(userModel.getUsername())
.password(userModel.getPassword())
// 账户启动
.enabled(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未过期(如果需要 请自行扩展字段)
.accountNonExpired(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 账户未锁定(如果需要 请自行扩展字段)
.accountNonLocked(
DictType.NO_YES_YES.getValue().equals(userModel.getEnable()))
// 判断凭证是否过期(默认不判断 如果需要 请自行扩展过期后修改密码操作)
.credentialsNonExpired(
PasswordUtil.isCredentialsNonExpired(
userModel.getPassword(), authProperties.getCredentialsExpired()))
// 授权信息
.authorities(grantedAuthorities)
.build();
return Optional.ofNullable(userDetailModel);
}
}

@ -1,46 +0,0 @@
package org.opsli.core.security.shiro.authenticator;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.realm.Realm;
import java.util.Collection;
/**
* 使TokenRealm
*
* @author Parker
* @date 2020-09-16
*/
public class CustomModularRealmAuthenticator extends ModularRealmAuthenticator {
/**
* Realm
* realm.supports()RealmRealmsupports()
* @param realms realm
* @param token token
* @return AuthenticationInfo
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
// 判断getRealms()是否返回为空
assertRealmsConfigured();
// 通过supports()方法匹配对应的Realm
Realm uniqueRealm = null;
for (Realm realm : realms) {
if (realm.supports(token)) {
uniqueRealm = realm;
break;
}
}
if (uniqueRealm == null) {
throw new UnsupportedTokenException();
}
return uniqueRealm.getAuthenticationInfo(token);
}
}

@ -1,256 +0,0 @@
package org.opsli.core.security.shiro.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.opsli.core.security.shiro.exception.PrincipalIdNullException;
import org.opsli.core.security.shiro.exception.PrincipalInstanceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author: sunzhiqiang
* @date: 2018/6/22
* @description: shiro-redis Git https://github.com/alexxiyang/shiro-redis
*/
public class RedisCache<K, V> implements Cache<K, V> {
private static Logger logger = LoggerFactory.getLogger(RedisCache.class);
private RedisManager redisManager;
private String keyPrefix = "";
private int expire = 0;
private String principalIdFieldName = RedisCacheManager.DEFAULT_PRINCIPAL_ID_FIELD_NAME;
/**
* Construction
* @param redisManager
*/
public RedisCache(RedisManager redisManager, String prefix, int expire, String principalIdFieldName) {
if (redisManager == null) {
throw new IllegalArgumentException("redisManager cannot be null.");
}
this.redisManager = redisManager;
if (prefix != null && !"".equals(prefix)) {
this.keyPrefix = prefix;
}
if (expire != -1) {
this.expire = expire;
}
if (principalIdFieldName != null && !"".equals(principalIdFieldName)) {
this.principalIdFieldName = principalIdFieldName;
}
}
@Override
public V get(K key) throws CacheException {
logger.debug("get key [{}]",key);
if (key == null) {
return null;
}
try {
String redisCacheKey = getRedisCacheKey(key);
Object rawValue = redisManager.get(redisCacheKey);
if (rawValue == null) {
return null;
}
V value = (V) rawValue;
return value;
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public V put(K key, V value) throws CacheException {
logger.debug("put key [{}]",key);
if (key == null) {
logger.warn("Saving a null key is meaningless, return value directly without call Redis.");
return value;
}
try {
String redisCacheKey = getRedisCacheKey(key);
redisManager.set(redisCacheKey, value != null ? value : null, expire);
return value;
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public V remove(K key) throws CacheException {
logger.debug("remove key [{}]",key);
if (key == null) {
return null;
}
try {
String redisCacheKey = getRedisCacheKey(key);
Object rawValue = redisManager.get(redisCacheKey);
V previous = (V) rawValue;
redisManager.del(redisCacheKey);
return previous;
} catch (Exception e) {
throw new CacheException(e);
}
}
private String getRedisCacheKey(K key) {
if (key == null) {
return null;
}
return this.keyPrefix + getStringRedisKey(key);
}
private String getStringRedisKey(K key) {
String redisKey;
if (key instanceof PrincipalCollection) {
redisKey = getRedisKeyFromPrincipalIdField((PrincipalCollection) key);
} else {
redisKey = key.toString();
}
return redisKey;
}
private String getRedisKeyFromPrincipalIdField(PrincipalCollection key) {
String redisKey;
Object principalObject = key.getPrimaryPrincipal();
Method pincipalIdGetter = null;
Method[] methods = principalObject.getClass().getDeclaredMethods();
for (Method m:methods) {
if (RedisCacheManager.DEFAULT_PRINCIPAL_ID_FIELD_NAME.equals(this.principalIdFieldName)
&& ("getAuthCacheKey".equals(m.getName()) || "getId".equals(m.getName()))) {
pincipalIdGetter = m;
break;
}
if (m.getName().equals("get" + this.principalIdFieldName.substring(0, 1).toUpperCase() + this.principalIdFieldName.substring(1))) {
pincipalIdGetter = m;
break;
}
}
if (pincipalIdGetter == null) {
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName);
}
try {
Object idObj = pincipalIdGetter.invoke(principalObject);
if (idObj == null) {
throw new PrincipalIdNullException(principalObject.getClass(), this.principalIdFieldName);
}
redisKey = idObj.toString();
} catch (IllegalAccessException e) {
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName, e);
} catch (InvocationTargetException e) {
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName, e);
}
return redisKey;
}
@Override
public void clear() throws CacheException {
logger.debug("clear cache");
Set<String> keys = null;
try {
keys = redisManager.scan(this.keyPrefix + "*");
} catch (Exception e) {
logger.error("get keys error", e);
}
if (keys == null || keys.size() == 0) {
return;
}
for (String key: keys) {
redisManager.del(key);
}
}
@Override
public int size() {
Long longSize = 0L;
try {
longSize = new Long(redisManager.scanSize(this.keyPrefix + "*"));
} catch (Exception e) {
logger.error("get keys error", e);
}
return longSize.intValue();
}
@SuppressWarnings("unchecked")
@Override
public Set<K> keys() {
Set<String> keys = null;
try {
keys = redisManager.scan(this.keyPrefix + "*");
} catch (Exception e) {
logger.error("get keys error", e);
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}
Set<K> convertedKeys = new HashSet<K>();
for (String key:keys) {
try {
convertedKeys.add((K) key);
} catch (Exception e) {
logger.error("deserialize keys error", e);
}
}
return convertedKeys;
}
@Override
public Collection<V> values() {
Set<String> keys = null;
try {
keys = redisManager.scan(this.keyPrefix + "*");
} catch (Exception e) {
logger.error("get values error", e);
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}
List<V> values = new ArrayList<V>(keys.size());
for (String key : keys) {
V value = null;
try {
value = (V) redisManager.get(key);
} catch (Exception e) {
logger.error("deserialize values= error", e);
}
if (value != null) {
values.add(value);
}
}
return Collections.unmodifiableList(values);
}
public String getKeyPrefix() {
return keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
public String getPrincipalIdFieldName() {
return principalIdFieldName;
}
public void setPrincipalIdFieldName(String principalIdFieldName) {
this.principalIdFieldName = principalIdFieldName;
}
}

@ -1,85 +0,0 @@
package org.opsli.core.security.shiro.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @description: shiro-redis Git https://github.com/alexxiyang/shiro-redis
*/
public class RedisCacheManager implements CacheManager {
private final Logger logger = LoggerFactory.getLogger(RedisCacheManager.class);
/**
* fast lookup by name map
*/
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
private RedisManager redisManager;
/**
* expire time in seconds
*/
private static final int DEFAULT_EXPIRE = 1800;
private int expire = DEFAULT_EXPIRE;
/**
* The Redis key prefix for caches
*/
public static final String DEFAULT_CACHE_KEY_PREFIX = "shiro:cache:";
private String keyPrefix = DEFAULT_CACHE_KEY_PREFIX;
public static final String DEFAULT_PRINCIPAL_ID_FIELD_NAME = "authCacheKey or id";
private String principalIdFieldName = DEFAULT_PRINCIPAL_ID_FIELD_NAME;
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
logger.debug("get cache, name={}",name);
Cache cache = caches.get(name);
if (cache == null) {
cache = new RedisCache<K, V>(redisManager,keyPrefix + name + ":", expire, principalIdFieldName);
caches.put(name, cache);
}
return cache;
}
public RedisManager getRedisManager() {
return redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
}
public String getKeyPrefix() {
return keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
public int getExpire() {
return expire;
}
public void setExpire(int expire) {
this.expire = expire;
}
public String getPrincipalIdFieldName() {
return principalIdFieldName;
}
public void setPrincipalIdFieldName(String principalIdFieldName) {
this.principalIdFieldName = principalIdFieldName;
}
}

@ -1,147 +0,0 @@
package org.opsli.core.security.shiro.cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
*
* @author sunzhiqiang
* springredisredisTemplate
*/
public class RedisManager {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//=============================common============================
/**
*
* @param key
* @param time ()
*/
public void expire(String key,long time){
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
/**
* key
* @param key
* @return true false
*/
public Boolean hasKey(String key){
return redisTemplate.hasKey(key);
}
/**
*
* @param key
*/
@SuppressWarnings("unchecked")
public void del(String ... key){
if(key!=null&&key.length>0){
if(key.length==1){
redisTemplate.delete(key[0]);
}else{
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
/**
* key
* @param keys
*/
public void del(Collection keys){
redisTemplate.delete(keys);
}
//============================String=============================
/**
*
* @param key
* @return
*/
public Object get(String key){
return redisTemplate.opsForValue().get(key);
}
/**
*
* @param key
* @param value
*/
public void set(String key,Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
*
* @param key
* @param value
* @param time () time0 time0
*/
public void set(String key,Object value,long time){
if(time>0){
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
}else{
set(key, value);
}
}
/**
* 使scan key
* @param key
* @return
*/
public Set<String> scan(String key){
Set<String> execute = this.redisTemplate.execute(new RedisCallback<Set<String>>() {
@Override
public Set<String> doInRedis(RedisConnection connection) throws DataAccessException {
Set<String> binaryKeys = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(key).count(1000).build());
while (cursor.hasNext()) {
binaryKeys.add(new String(cursor.next()));
}
return binaryKeys;
}
});
return execute;
}
/**
* 使scan key
* session,线
* @param key
* @return
*/
public Long scanSize(String key){
long dbSize = this.redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
long count = 0L;
Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(key).count(1000).build());
while (cursor.hasNext()) {
cursor.next();
count++;
}
return count;
}
});
return dbSize;
}
}

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

Loading…
Cancel
Save