代码提交

This commit is contained in:
2023-06-08 11:28:13 +08:00
parent b53456d41c
commit ec6e27a4eb
23 changed files with 1308 additions and 4 deletions

View File

@@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.enums.response.CommonResponseEnum; import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException; import com.njcn.common.pojo.exception.BusinessException;
@@ -26,6 +27,8 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Integer.parseInt; import static java.lang.Integer.parseInt;
@@ -306,4 +309,22 @@ public class PubUtils {
return -1; return -1;
} }
} }
//*****************************************xuyang添加,用于App********************************************************
/**
* 正则表达式字符串
* 要匹配的字符串
*
* @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
*/
public static boolean match(String regex, String str) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
public static boolean patternPasswordPhone(String password) {
return match(PatternRegex.PASSWORD_PHONE_REGEX, password);
}
//***************************************************添加结束********************************************************
} }

View File

@@ -0,0 +1,88 @@
package com.njcn.web.utils.app;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
/**
* @author hongawen
* @date: 2019/10/28 14:37
*/
public class AESUtil {
private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
private static final String key ="f81804778c89c779";
private static final String EncryptAlg ="AES";
private static final String Cipher_Mode="AES/ECB/PKCS5Padding";
private static final String Encode="UTF-8";
private static final int Secret_Key_Size=16;
private static final String Key_Encode="UTF-8";
/**
* @param content 加密内容
* @return aes加密后 转base64
*/
public static String aesPKCS5PaddingEncrypt(String content) throws Exception {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(Cipher_Mode);
byte[] realKey=getSecretKey(key);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(realKey,EncryptAlg));
byte[] data=cipher.doFinal(content.getBytes(Encode));
String result=new Base64().encodeToString(data);
return result;
} catch (Exception e) {
throw new Exception("AES加密失败content=" +content +" key="+key);
}
}
/**
* AES/ECB/PKCS7Padding 解密
* @param content 解密内容
* @return 先转base64 再解密
*/
public static String aesPKCS5PaddingDecrypt(String content) throws Exception {
try {
byte[] decodeBytes= Base64.decodeBase64(content);
Cipher cipher = Cipher.getInstance(Cipher_Mode);
byte[] realKey=getSecretKey(key);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(realKey,EncryptAlg));
byte[] realBytes=cipher.doFinal(decodeBytes);
return new String(realBytes, Encode);
} catch (Exception e) {
throw new Exception("AES解密失败Aescontent = " +e.fillInStackTrace(),e);
}
}
/**
* 对密钥key进行处理如密钥长度不够位数的则 以指定paddingChar 进行填充;
* 此处用空格字符填充,也可以 0 填充,具体可根据实际项目需求做变更
* @param key
* @return
* @throws Exception
*/
public static byte[] getSecretKey(String key) throws Exception{
final byte paddingChar=' ';
byte[] realKey = new byte[Secret_Key_Size];
byte[] byteKey = key.getBytes(Key_Encode);
for (int i =0;i<realKey.length;i++){
if (i<byteKey.length){
realKey[i] = byteKey[i];
}else {
realKey[i] = paddingChar;
}
}
return realKey;
}
}

View File

@@ -0,0 +1,211 @@
package com.njcn.web.utils.app;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* @author hongawen //denghuajun
* @version 1.0
* @Date 2018/4/20 9:00
*/
public class XssFilterUtil {
/**
* 处理参数值
* @param parameters 字符数组
*/
public static String[] dealStringArray(String[] parameters) {
if (ArrayUtils.isEmpty(parameters)) {
return null;
}
int count = parameters.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = dealString(parameters[i]);
}
return encodedValues;
}
/**
* 处理参数值
* @param parameters 字符集合
*/
public static String[] dealStringList(List<String> parameters) {
if (CollectionUtils.isEmpty(parameters)) {
return null;
}
int count = parameters.size();
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = dealString(parameters.get(i));
}
return encodedValues;
}
/**
* 滤除content中的危险 HTML 代码, 主要是脚本代码, 滚动字幕代码以及脚本事件处理代码
*
* @param content
* 需要滤除的字符串
* @return 过滤的结果
*/
public static String replaceHtmlCode(String content) {
if (null == content) {
return null;
}
if (0 == content.length()) {
return "";
}
// 需要滤除的脚本事件关键字
String[] eventKeywords = { "onmouseover", "onmouseout", "onmousedown",
"onmouseup", "onmousemove", "onclick", "ondblclick",
"onkeypress", "onkeydown", "onkeyup", "ondragstart",
"onerrorupdate", "onhelp", "onreadystatechange", "onrowenter",
"onrowexit", "onselectstart", "onload", "onunload",
"onbeforeunload", "onblur", "onerror", "onfocus", "onresize",
"onscroll", "oncontextmenu", "alert" };
content = replace(content, "<script", "<script", false);
content = replace(content, "</script", "</script", false);
content = replace(content, "<marquee", "<marquee", false);
content = replace(content, "</marquee", "</marquee", false);
// content = replace(content, "'", "_", false);// 将单引号替换成下划线
// content = replace(content, "\"", "_", false);// 将双引号替换成下划线
// 滤除脚本事件代码
for (int i = 0; i < eventKeywords.length; i++) {
content = replace(content, eventKeywords[i],
"_" + eventKeywords[i], false); // 添加一个"_", 使事件代码无效
}
return content;
}
/**
* 将字符串 source 中的 oldStr 替换为 newStr, 并以大小写敏感方式进行查找
*
* @param source
* 需要替换的源字符串
* @param oldStr
* 需要被替换的老字符串
* @param newStr
* 替换为的新字符串
*/
private static String replace(String source, String oldStr, String newStr) {
return replace(source, oldStr, newStr, true);
}
/**
* 将字符串 source 中的 oldStr 替换为 newStr, matchCase 为是否设置大小写敏感查找
*
* @param source
* 需要替换的源字符串
* @param oldStr
* 需要被替换的老字符串
* @param newStr
* 替换为的新字符串
* @param matchCase
* 是否需要按照大小写敏感方式查找
*/
private static String replace(String source, String oldStr, String newStr,
boolean matchCase) {
if (source == null) {
return null;
}
// 首先检查旧字符串是否存在, 不存在就不进行替换
if (source.toLowerCase().indexOf(oldStr.toLowerCase()) == -1) {
return source;
}
int findStartPos = 0;
int a = 0;
while (a > -1) {
int b = 0;
String str1, str2, str3, str4, strA, strB;
str1 = source;
str2 = str1.toLowerCase();
str3 = oldStr;
str4 = str3.toLowerCase();
if (matchCase) {
strA = str1;
strB = str3;
} else {
strA = str2;
strB = str4;
}
a = strA.indexOf(strB, findStartPos);
if (a > -1) {
b = oldStr.length();
findStartPos = a + b;
StringBuffer bbuf = new StringBuffer(source);
source = bbuf.replace(a, a + b, newStr) + "";
// 新的查找开始点位于替换后的字符串的结尾
findStartPos = findStartPos + newStr.length() - b;
}
}
return source;
}
public static String xssEncode(String s) {
if (s == null || s.isEmpty()) {
return s;
}
StringBuilder sb = new StringBuilder(s.length() + 16);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '>':
sb.append('');// 全角大于号
break;
case '<':
sb.append('');// 全角小于号
break;
// case '\'':
// sb.append('');// 全角单引号
// break;
// case '\"':
// sb.append('“');// 全角双引号
// break;
// case '&':
// sb.append('');// 全角
// break;
case '\\':
sb.append('');// 全角斜线
break;
/*case '#':
sb.append('');// 全角井号
break;*/
// case '(':
// sb.append('');//
// break;
// case ')':
// sb.append('');//
// break;
default:
sb.append(c);
break;
}
}
String resultStr = sb.toString();
// resultStr=StringEscapeUtils.escapeSql(resultStr);
// resultStr=StringEscapeUtils.escapeHtml(resultStr);
// resultStr=StringEscapeUtils.escapeJavaScript(resultStr);
return resultStr;
}
/**
* 字符串处理包括SQL的注入处理
* @author hongawen
* @param value 字符串
*/
public static String dealString(String value) {
if (!StringUtils.isBlank(value)) {
value = xssEncode(value);
value=replaceHtmlCode(value);
value= StringEscapeUtils.escapeSql(value);
return value;
}else{
return "";
}
}
}

View File

@@ -3,5 +3,5 @@ spring:
url: http://192.168.1.16:8086 url: http://192.168.1.16:8086
user: admin user: admin
password: 123456 password: 123456
database: pqsbase_sjzx database: pqsbase_zl
mapper-location: com.njcn.influx.imapper mapper-location: com.njcn.influx.imapper

View File

@@ -1,7 +1,9 @@
package com.njcn.influx; package com.njcn.influx;
import com.njcn.influx.imapper.CldStatisticsFlowMapper; import com.njcn.influx.imapper.CldStatisticsFlowMapper;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.influx.pojo.po.DataV; import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.service.CommonService;
import com.njcn.influx.service.DataFlickerService; import com.njcn.influx.service.DataFlickerService;
import com.njcn.influx.service.IDataVService; import com.njcn.influx.service.IDataVService;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@@ -26,12 +28,19 @@ public class DemoTest extends BaseJunitTest {
@Autowired @Autowired
private IDataVService dataVService; private IDataVService dataVService;
@Autowired
private CommonService commonService;
@SneakyThrows @SneakyThrows
@Test @Test
public void test() { public void test() {
// dataFlickerService.getDataFlicker("ff2d9674c1f1ecce7f33a5bf17fc4f2d","2023-05-02 00:00:00","2023-05-02 23:59:59"); // dataFlickerService.getDataFlicker("ff2d9674c1f1ecce7f33a5bf17fc4f2d","2023-05-02 00:00:00","2023-05-02 23:59:59");
List<DataV> ss = dataVService.getDataV("ff2d9674c1f1ecce7f33a5bf17fc4f2d", "2023-05-02 00:00:00", "2023-05-02 23:59:59"); // List<DataV> ss = dataVService.getDataV("ff2d9674c1f1ecce7f33a5bf17fc4f2d", "2023-05-02 00:00:00", "2023-05-02 23:59:59");
System.out.println(ss); // System.out.println(ss);
StatisticalDataDTO statisticalDataDTO = commonService.getLineRtData("4","data_harmpower_p","W","A","max");
System.out.println("statisticalDataDTO==:" + statisticalDataDTO);
} }

View File

@@ -0,0 +1,46 @@
package com.njcn.user.enums;
/**
* @author hongawen
* @date: 2019/10/22 14:05
* 短信模板枚举
*/
public enum MessageEnum {
/**
* 阿里云短信模板编号
*/
LOGIN(0, "SMS_176180086"),
REGISTER(1, "SMS_176200101"),
RESET_PWD(2, "SMS_176195072"),
FORGET_PWD(3, "SMS_176195072"),
UPDATE_PHONE(4, "SMS_175583840"),
JUDGE_OLD_PHONE(5, "SMS_176195072"),
EVENT_MESSAGE_NOTICE(6,"SMS_212270827");
private final int code;
private final String templateCode;
MessageEnum(int code, String templateCode) {
this.code = code;
this.templateCode = templateCode;
}
public int getCode() {
return code;
}
public String getTemplateCode() {
return templateCode;
}
public static String getTemplateByCode(int code) {
for (MessageEnum messageEnum : MessageEnum.values()) {
if (messageEnum.code == code) {
return messageEnum.templateCode;
}
}
return "";
}
}

View File

@@ -0,0 +1,51 @@
package com.njcn.user.enums;
/**
* @author hongawen
* @date: 2019/10/28 15:11
*/
public enum UserLevelEnum {
HOST_USER("0","主用户"),
CHILD_USER("1","子用户"),
OPERATION_USER("2","运维"),
SPECIFIC_USER("3","专职"),
ENGINEERING_USER("4","工程"),
TOURIST_USER("5","游客");
private String code;
private String msg;
UserLevelEnum(String code, String msg){
this.code=code;
this.msg=msg;
}
public String getCode(){
return code;
}
public String getMsg(){
return msg;
}
public static String getMsgByCode(String code){
for (UserLevelEnum userLevelEnum : UserLevelEnum.values()) {
if (userLevelEnum.code.equalsIgnoreCase(code)) {
return userLevelEnum.msg;
}
}
return "";
}
public static String getCodeByMsg(String msg){
for (UserLevelEnum userLevelEnum : UserLevelEnum.values()) {
if (userLevelEnum.msg.equalsIgnoreCase(msg)) {
return userLevelEnum.code;
}
}
return "";
}
}

View File

@@ -22,18 +22,25 @@ public enum UserResponseEnum {
*/ */
LOGIN_USERNAME_NOT_FOUND("A0101", "用户不存在"), LOGIN_USERNAME_NOT_FOUND("A0101", "用户不存在"),
LOGIN_USERNAME_INVALID("A0101", "用户名非法"), LOGIN_USERNAME_INVALID("A0101", "用户名非法"),
LOGIN_USER_INDEX_INVALID("A0101", "用户索引非法"),
LOGIN_PHONE_NOT_FOUND("A0101", "手机号不存在"), LOGIN_PHONE_NOT_FOUND("A0101", "手机号不存在"),
KEY_WRONG("A0101","登录密码/验证码为空"),
LOGIN_WRONG_PWD("A0101", "用户名密码错误"), LOGIN_WRONG_PWD("A0101", "用户名密码错误"),
LOGIN_WRONG_PHONE_CODE("A0101", "短信验证码错误"), LOGIN_WRONG_PHONE_CODE("A0101", "短信验证码错误"),
LOGIN_WRONG_CODE("A0101", "验证码错误"), LOGIN_WRONG_CODE("A0101", "验证码错误"),
CODE_TYPE_ERROR("A0101","验证码类型非法"),
SEND_CODE_FAIL("A0101","验证码发送失败"),
LOGIN_USER_DELETE("A0101", "账号已被注销"), LOGIN_USER_DELETE("A0101", "账号已被注销"),
LOGIN_USER_LOCKED("A0101", "账号已被锁定"), LOGIN_USER_LOCKED("A0101", "账号已被锁定"),
LOGIN_USER_UNAUDITED("A0101", "账号未审核"), LOGIN_USER_UNAUDITED("A0101", "账号未审核"),
NEED_MODIFY_PASSWORD("A0101", "密码需修改"), NEED_MODIFY_PASSWORD("A0101", "密码需修改"),
LOGIN_USER_SLEEP("A0101", "账号已休眠"), LOGIN_USER_SLEEP("A0101", "账号已休眠"),
LOGIN_USER_PASSWORD_EXPIRED("A0101", "账号密码过期"), LOGIN_USER_PASSWORD_EXPIRED("A0101", "账号密码过期"),
LOGIN_ERROR("A0101", "登录失败"),
LOGIN_FIRST_LOGIN("A0101", "账号首次登录"), LOGIN_FIRST_LOGIN("A0101", "账号首次登录"),
NEED_MODIFY_PWD("A0101", "密码失效,请重置"), NEED_MODIFY_PWD("A0101", "密码失效,请重置"),
PASSWORD_INVALID("A0101", "密码非法"),
PASSWORD_SET_ERROR("A0101", "密码设置错误"),
LACK_USER_STRATEGY("A0101", "缺失用户策略配置"), LACK_USER_STRATEGY("A0101", "缺失用户策略配置"),
UNSUPPORTED_GRANT_TYPE("A0101", "非法认证方式"), UNSUPPORTED_GRANT_TYPE("A0101", "非法认证方式"),
INVALID_IP("A0101", "非法IP访问系统"), INVALID_IP("A0101", "非法IP访问系统"),
@@ -42,10 +49,13 @@ public enum UserResponseEnum {
SPECIAL_PASSWORD("A0101", "密码需要包含特殊字符字母数字长度为8-16"), SPECIAL_PASSWORD("A0101", "密码需要包含特殊字符字母数字长度为8-16"),
REPEAT_PASSWORD("A0101", "新密码与旧密码不能一致"), REPEAT_PASSWORD("A0101", "新密码与旧密码不能一致"),
REGISTER_FAIL("A0102", "注册失败"),
REGISTER_PHONE_FAIL("A0102", "该号码已注册,请检查phone字段"), REGISTER_PHONE_FAIL("A0102", "该号码已注册,请检查phone字段"),
REGISTER_LOGIN_NAME_FAIL("A0102", "该账号已注册"), REGISTER_LOGIN_NAME_FAIL("A0102", "该账号已注册"),
REGISTER_PHONE_WRONG("A0102", "手机号非法"), REGISTER_PHONE_WRONG("A0102", "手机号非法"),
REGISTER_PHONE_REPEAT("A0102", "手机号已注册"),
REGISTER_PASSWORD_WRONG("A0102", "账号密码非法"), REGISTER_PASSWORD_WRONG("A0102", "账号密码非法"),
DEV_CODE_WRONG("A0102","设备码非法"),
REGISTER_LOGIN_NAME_EXIST("A0102", "该登录名已存在,请检查loginName字段"), REGISTER_LOGIN_NAME_EXIST("A0102", "该登录名已存在,请检查loginName字段"),
REGISTER_HOMEPAGE_NAME_EXIST("A0102", "该驾驶舱名已存在,请检查name字段"), REGISTER_HOMEPAGE_NAME_EXIST("A0102", "该驾驶舱名已存在,请检查name字段"),
FUNCTION_PATH_EXIST("A0102", "菜单路径已存在,请检查path字段"), FUNCTION_PATH_EXIST("A0102", "菜单路径已存在,请检查path字段"),
@@ -95,4 +105,13 @@ public enum UserResponseEnum {
this.message = message; this.message = message;
} }
public static String getCodeByMsg(String msg){
for (UserResponseEnum userCodeEnum : UserResponseEnum.values()) {
if (userCodeEnum.message.equalsIgnoreCase(msg)) {
return userCodeEnum.code;
}
}
return "";
}
} }

View File

@@ -0,0 +1,51 @@
package com.njcn.user.pojo.po.app;
import com.baomidou.mybatisplus.annotation.TableName;
import com.njcn.db.bo.BaseEntity;
import java.io.Serializable;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* APP用户消息配置表
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
@Data
@TableName("app_info_set")
public class AppInfoSet {
private static final long serialVersionUID = 1L;
/**
* 用户id
*/
private String userIndex;
/**
* 0false 1true 暂态消息模块
*/
private Integer eventInfo;
/**
* 0false 1true 稳态消息模块
*/
private Integer harmonicInfo;
/**
* 0false 1true 终端消息模块
*/
private Integer deviceInfo;
/**
* 0false 1true 系统消息模块
*/
private Integer systemInfo;
}

View File

@@ -0,0 +1,47 @@
package com.njcn.user.pojo.po.app;
import com.baomidou.mybatisplus.annotation.TableName;
import com.njcn.db.bo.BaseEntity;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* App手机验证码发送记录表
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
@Data
@TableName("app_send_msg")
public class AppSendMsg {
private static final long serialVersionUID = 1L;
/**
* 手机号
*/
private String phone;
/**
* 消息内容
*/
private String message;
/**
* 发送时间
*/
private LocalDateTime sendTime;
/**
* 发送状态
*/
private String sendStatus;
}

View File

@@ -0,0 +1,117 @@
package com.njcn.user.pojo.po.app;
import com.baomidou.mybatisplus.annotation.TableName;
import com.njcn.db.bo.BaseEntity;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* App用户表
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
@Data
@TableName("app_user")
public class AppUser extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 用户表Guid
*/
private String userIndex;
/**
* 用户名(别名)
*/
private String name;
/**
* 登录名
*/
private String loginName;
/**
* 密码
*/
private String password;
/**
* 电话号码
*/
private String phone;
/**
* 邮箱
*/
private String email;
/**
* 注册时间
*/
private LocalDateTime registerTime;
/**
* 密码有效期字段(初始化的时候跟注册时间一样)
*/
private LocalDateTime psdValidity;
/**
* 最后一次登录时间
*/
private LocalDateTime loginTime;
/**
* 用户状态0删除1正常2锁定
*/
private Integer state;
/**
* 密码错误次数
*/
private Integer loginErrorTimes;
/**
* 第一次登陆错误的时间
*/
private LocalDateTime loginFirstErrorTime;
/**
* 营销人员名称(只针对主用户)
*/
private String semName;
/**
* 营销人员手机(只针对主用户)
*/
private String semPhone;
/**
* 推荐码(新增主用户时候生成)
*/
private String referralCode;
/**
* 设备码
*/
private String devCode;
/**
* 用户类型0主用户1子用户2运维3专职4:工程5游客
*/
private Integer userType;
/**
* 用户等级
*/
private String userLevel;
}

View File

@@ -0,0 +1,25 @@
package com.njcn.user.pojo.vo.app;
import lombok.Data;
/**
* 类的介绍:
*
* @author xuyang
* @version 1.0.0
* @createTime 2023/6/8 9:37
*/
@Data
public class AppUserResultVO {
private String userId;
private String roleName;
private String phone;
private String userName;
private String roleCode;
}

View File

@@ -44,7 +44,18 @@
<artifactId>common-swagger</artifactId> <artifactId>common-swagger</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!--阿里云发送短信-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.1.0</version>
</dependency>
<!--阿里云发送短信结束-->
</dependencies> </dependencies>
<build> <build>

View File

@@ -0,0 +1,141 @@
package com.njcn.user.controller.app;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
import com.njcn.user.service.IAppUserService;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.app.AESUtil;
import com.njcn.web.utils.app.XssFilterUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.ocsp.ResponseData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 类的介绍:
*
* @author xuyang
* @version 1.0.0
* @createTime 2023/6/7 8:51
*/
@Validated
@Slf4j
@RestController
@RequestMapping("/appUser")
@Api(tags = "App用户信息管理")
@AllArgsConstructor
public class AppUserController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(AppUserController.class);
private final IAppUserService appUserService;
/**
* 获取(登录、注册、忘记密码、重新绑定手机)验证码
*/
@PostMapping("authCode")
@OperateInfo
@ApiOperation(value = "获取验证码", notes = "获取验证码")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
@ApiImplicitParam(name = "type", value = "验证码类型", required = true, paramType = "query"),
})
public HttpResult<String> authCode(String phone, String devCode, String type) {
String methodDescribe = getMethodDescribe("authCode");
appUserService.setMessage(phone,devCode,type);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, "success", methodDescribe);
}
/**
* 手机app注册
*/
@PostMapping("register")
@OperateInfo
@ApiOperation(value = "注册入口", notes = "用户注册")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<AppUserResultVO> register(String phone, String code, String devCode) {
String methodDescribe = getMethodDescribe("register");
AppUserResultVO appUserResultVo = appUserService.register(phone,code,devCode);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, appUserResultVo, methodDescribe);
}
/**
* 手机app密码设置
*/
@PostMapping("setPsd")
@OperateInfo
@ApiOperation(value = "设置密码", notes = "设置密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户索引", required = true, paramType = "query"),
@ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<String> setPsd(String userId, String password, String devCode) {
String methodDescribe = getMethodDescribe("setPsd");
appUserService.setPsd(userId, devCode, password);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, "success", methodDescribe);
}
/**
* 手机app登录入口
*/
@PostMapping("login")
@OperateInfo
@ApiOperation(value = "登录入口", notes = "APP登录")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query"),
@ApiImplicitParam(name = "type", value = "登录类型", required = true, paramType = "query"),
@ApiImplicitParam(name = "key", value = "验证码/密码", required = true, paramType = "query"),
@ApiImplicitParam(name = "devCode", value = "设备码", required = true, paramType = "query"),
})
public HttpResult<AppUserResultVO> login(String phone, String type, String key, String devCode, HttpServletRequest request) {
String methodDescribe = getMethodDescribe("login");
AppUserResultVO appUserResultVo = appUserService.login(phone,type,key,devCode);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, appUserResultVo, methodDescribe);
}
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
/**
* <p>
* APP用户消息配置表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
public interface AppInfoSetMapper extends BaseMapper<AppInfoSet> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppSendMsg;
/**
* <p>
* App手机验证码发送记录表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface AppSendMsgMapper extends BaseMapper<AppSendMsg> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.user.pojo.po.app.AppUser;
/**
* <p>
* App用户表 Mapper 接口
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface AppUserMapper extends BaseMapper<AppUser> {
}

View File

@@ -0,0 +1,16 @@
package com.njcn.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.user.pojo.po.app.AppInfoSet;
/**
* <p>
* APP用户消息配置表 服务类
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
public interface IAppInfoSetService extends IService<AppInfoSet> {
}

View File

@@ -0,0 +1,15 @@
package com.njcn.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.user.pojo.po.app.AppSendMsg;
/**
* <p>
* App手机验证码发送记录表 服务类
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
public interface IAppSendMsgService extends IService<AppSendMsg> {
}

View File

@@ -0,0 +1,43 @@
package com.njcn.user.service;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
/**
* @author xuyang
*/
public interface IAppUserService {
/**
* 发送短信
* @param phone 手机号
* @param devCode 设备码
* @param type 验证码类型
*/
void setMessage(String phone, String devCode, String type);
/**
* 手机app注册(所有用户初始统一为游客,需要特定的码升级)
* @param phone 手机号
* @param code 验证码
* @param devCode 设备码
*/
AppUserResultVO register(String phone, String code, String devCode);
/**
* 用户设置密码
* @param userId 用户id
* @param devCode 设备码
* @param password 密码
*/
void setPsd(String userId, String devCode, String password);
/**
* 用户设置密码
* @param phone 手机号
* @param type 登陆类型
* @param key 验证码/密码
* @param devCode 设备码
*/
AppUserResultVO login(String phone, String type, String key, String devCode);
}

View File

@@ -0,0 +1,20 @@
package com.njcn.user.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.user.mapper.AppInfoSetMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
import com.njcn.user.service.IAppInfoSetService;
import org.springframework.stereotype.Service;
/**
* <p>
* APP用户消息配置表 服务实现类
* </p>
*
* @author xuyang
* @since 2023-06-08
*/
@Service
public class AppInfoSetServiceImpl extends ServiceImpl<AppInfoSetMapper, AppInfoSet> implements IAppInfoSetService {
}

View File

@@ -0,0 +1,20 @@
package com.njcn.user.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.user.mapper.AppSendMsgMapper;
import com.njcn.user.pojo.po.app.AppSendMsg;
import com.njcn.user.service.IAppSendMsgService;
import org.springframework.stereotype.Service;
/**
* <p>
* App手机验证码发送记录表 服务实现类
* </p>
*
* @author xuyang
* @since 2023-06-07
*/
@Service
public class AppSendMsgServiceImpl extends ServiceImpl<AppSendMsgMapper, AppSendMsg> implements IAppSendMsgService {
}

View File

@@ -0,0 +1,305 @@
package com.njcn.user.service.impl;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.constant.PatternRegex;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.user.enums.MessageEnum;
import com.njcn.user.enums.UserLevelEnum;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.mapper.AppUserMapper;
import com.njcn.user.pojo.po.app.AppInfoSet;
import com.njcn.user.pojo.po.app.AppSendMsg;
import com.njcn.user.pojo.po.app.AppUser;
import com.njcn.user.pojo.vo.app.AppUserResultVO;
import com.njcn.user.service.IAppInfoSetService;
import com.njcn.user.service.IAppSendMsgService;
import com.njcn.user.service.IAppUserService;
import com.njcn.web.utils.app.AESUtil;
import com.njcn.web.utils.app.XssFilterUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Random;
/**
* 类的介绍:
*
* @author xuyang
* @version 1.0.0
* @createTime 2023/6/7 14:42
*/
@Service
@AllArgsConstructor
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements IAppUserService {
private static final Logger logger = LoggerFactory.getLogger(AppUserServiceImpl.class);
private final RedisUtil redisUtil;
private final IAppSendMsgService appSendMsgService;
private final IAppInfoSetService appInfoSetService;
@Override
@Transactional(rollbackFor = Exception.class)
public void setMessage(String phone, String devCode, String type) {
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
String msgTemplate;
switch (type) {
case "0":
msgTemplate = MessageEnum.getTemplateByCode(0);
break;
case "1":
msgTemplate = MessageEnum.getTemplateByCode(1);
break;
case "2":
msgTemplate = MessageEnum.getTemplateByCode(2);
break;
case "3":
msgTemplate = MessageEnum.getTemplateByCode(3);
break;
case "4":
msgTemplate = MessageEnum.getTemplateByCode(4);
break;
case "5":
msgTemplate = MessageEnum.getTemplateByCode(5);
break;
default:
throw new BusinessException(UserResponseEnum.CODE_TYPE_ERROR);
}
//type为4账号替换为新手机号
if (!msgTemplate.equalsIgnoreCase(MessageEnum.REGISTER.getTemplateCode())) {
AppUser appUser = this.lambdaQuery().eq(AppUser::getPhone,phone).one();
if ("4".equalsIgnoreCase(type)) {
//注册,无需判断手机号与设备的匹配
if (appUser != null) {
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_FAIL);
}
} else {
if (null == appUser) {
throw new BusinessException(UserResponseEnum.LOGIN_USERNAME_NOT_FOUND);
} else {
appUser.setDevCode(devCode);
logger.info("更新手机id" + devCode);
this.updateById(appUser);
}
}
}
//开始执行短信发送
//设置超时时间-可自行调整
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化ascClient需要的几个参数
//短信API产品名称短信产品名固定无需修改
final String product = "Dysmsapi";
//短信API产品域名接口地址固定无需修改
final String domain = "dysmsapi.aliyuncs.com";
//替换成你的AK
//你的accessKeyId,参考本文档步骤2
final String accessKeyId = "LTAI4FxsR76x2dq3w9c5puUe";
//你的accessKeySecret参考本文档步骤2
final String accessKeySecret = "GxkTR8fsrvHtixTlD9UPmOGli35tZs";
//初始化ascClient,暂时不支持多region请勿修改
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setMethod(MethodType.POST);
request.setPhoneNumbers(phone);
//必填:短信签名-可在短信控制台中找到
request.setSignName("灿能云");
//必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版
request.setTemplateCode(msgTemplate);
String vcode = getMessageCode();
String code = "{\"code\":\"" + vcode + "\"}";
request.setTemplateParam(code);
//请求失败这里会抛ClientException异常
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
String key = phone + devCode;
if (sendSmsResponse.getCode() != null && "OK".equals(sendSmsResponse.getCode())) {
//成功发送短信验证码后保存进redis
redisUtil.saveByKeyWithExpire(key, vcode, 300L);
} else {
throw new BusinessException(UserResponseEnum.SEND_CODE_FAIL);
}
AppSendMsg appSendMsg = new AppSendMsg();
appSendMsg.setPhone(phone);
appSendMsg.setMessage(vcode);
appSendMsg.setSendTime(LocalDateTime.now());
appSendMsg.setSendStatus(sendSmsResponse.getCode() == null ? "无状态" : sendSmsResponse.getCode());
appSendMsgService.save(appSendMsg);
} catch (Exception e) {
logger.error("发送短信异常,异常为:"+e.getMessage());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.SEND_CODE_FAIL);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public AppUserResultVO register(String phone, String code, String devCode) {
AppUserResultVO appUserResultVo = new AppUserResultVO();
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
judgeCode(phone, code, devCode);
//先根据手机号查询是否已被注册
AppUser appUser = this.lambdaQuery().eq(AppUser::getPhone,phone).one();
if (!Objects.isNull(appUser)){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_REPEAT);
} else {
appUser = new AppUser();
appUser.setPhone(phone);
appUser.setLoginErrorTimes(0);
appUser.setLoginTime(LocalDateTime.now());
appUser.setPsdValidity(appUser.getLoginTime());
appUser.setRegisterTime(appUser.getLoginTime());
appUser.setUserLevel("5");
appUser.setDevCode(devCode);
logger.info("插入手机id" + devCode);
appUser.setReferralCode("DUCxda");
appUser.setState(1);
this.save(appUser);
//消息默认配置
AppInfoSet appInfoSet = new AppInfoSet();
appInfoSet.setUserIndex(appUser.getUserIndex());
appInfoSet.setDeviceInfo(1);
appInfoSet.setEventInfo(1);
appInfoSet.setSystemInfo(1);
appInfoSet.setHarmonicInfo(1);
appInfoSetService.save(appInfoSet);
//配置返回数据
appUserResultVo.setUserId(appUser.getUserIndex());
appUserResultVo.setRoleName(UserLevelEnum.getMsgByCode(appUser.getUserLevel()));
appUserResultVo.setPhone(appUser.getPhone());
appUserResultVo.setRoleCode(appUser.getUserLevel());
appUserResultVo.setUserName(StringUtils.isEmpty(appUser.getName()) ? null : appUser.getName());
}
} catch (Exception e) {
logger.error("app用户注册异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.REGISTER_FAIL);
}
}
return appUserResultVo;
}
@Override
public void setPsd(String userId, String devCode, String password) {
//参数校验
if (StringUtils.isBlank(userId)) {
throw new BusinessException(UserResponseEnum.LOGIN_USER_INDEX_INVALID);
}
if (StringUtils.isBlank(userId)) {
throw new BusinessException(UserResponseEnum.PASSWORD_INVALID);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
//查看是否存在该用户
AppUser appUser = this.lambdaQuery().eq(AppUser::getUserIndex,userId).one();
if (Objects.isNull(appUser)){
throw new BusinessException(UserResponseEnum.LOGIN_USERNAME_NOT_FOUND);
} else {
String appPwd = AESUtil.aesPKCS5PaddingEncrypt(password);
appUser.setPassword(appPwd);
appUser.setDevCode(devCode);
logger.info("更新手机id" + devCode);
this.updateById(appUser);
}
} catch (Exception e) {
logger.error("app用户设置密码异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.PASSWORD_SET_ERROR);
}
}
}
@Override
public AppUserResultVO login(String phone, String type, String key, String devCode) {
//参数校验
if (!PubUtils.match(PatternRegex.PHONE_REGEX, XssFilterUtil.dealString(phone))){
throw new BusinessException(UserResponseEnum.REGISTER_PHONE_WRONG);
}
if (StringUtils.isBlank(key)) {
throw new BusinessException(UserResponseEnum.KEY_WRONG);
}
if (StringUtils.isBlank(devCode)) {
throw new BusinessException(UserResponseEnum.DEV_CODE_WRONG);
}
AppUserResultVO vo = new AppUserResultVO();
try {
devCode= AESUtil.aesPKCS5PaddingDecrypt(devCode);
} catch (Exception e) {
logger.error("app用户设置密码异常" + e.toString());
if (e.getMessage().length() < 10) {
throw new BusinessException(UserResponseEnum.getCodeByMsg(e.getMessage()));
} else {
throw new BusinessException(UserResponseEnum.LOGIN_ERROR);
}
}
return vo;
}
/**
* 自定义获取验证码,固定为字母和数字的组合
*/
private String getMessageCode() {
String result = "";
char[] numbers = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
//填充数字
for (int i = 0; i < 6; i++) {
int numberIndex = new Random().nextInt(10);
result = result + numbers[numberIndex];
}
return result;
}
private void judgeCode(String phone, String code, String devCode) {
String key = phone + devCode;
String redisCode = redisUtil.getStringByKey(key);
if (StringUtils.isEmpty(redisCode) || !code.equalsIgnoreCase(redisCode)) {
throw new BusinessException(UserResponseEnum.LOGIN_WRONG_CODE);
} else {
//存在且正确的验证,用完即删
redisUtil.delete(key);
}
}
}