mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 12:56:28 +08:00
5.0
This commit is contained in:
@@ -4,9 +4,12 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-parent</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>sop-admin</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
|
@@ -4,41 +4,18 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.15</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-admin</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-admin-backend</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<!-- springboot 版本-->
|
||||
<spring-boot.version>2.6.15</spring-boot.version>
|
||||
<!-- spring cloud 版本 -->
|
||||
<spring-cloud.version>2021.0.5</spring-cloud.version>
|
||||
<!-- spring cloud alibaba 版本 -->
|
||||
<!-- 具体版本对应关系见:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E -->
|
||||
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
|
||||
<!-- dubbo版本 -->
|
||||
<dubbo.version>3.2.10</dubbo.version>
|
||||
|
||||
<junit.version>4.11</junit.version>
|
||||
<commons-io.version>2.5</commons-io.version>
|
||||
<commons-fileupload.version>1.3.3</commons-fileupload.version>
|
||||
<commons-collection.version>3.2.2</commons-collection.version>
|
||||
<commons-lang3.version>3.8.1</commons-lang3.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<commons-logging.version>1.2</commons-logging.version>
|
||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||
<hibernate-validator.version>6.0.13.Final</hibernate-validator.version>
|
||||
<fastmybatis.version>3.0.12</fastmybatis.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -150,110 +127,6 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- 加了这个就不需要加版本号了 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||
<version>${spring-cloud-alibaba.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-bom</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.gitee.durcframework</groupId>
|
||||
<artifactId>fastmybatis-spring-boot-starter</artifactId>
|
||||
<version>${fastmybatis.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.14.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- commons -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>${commons-collection.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons-fileupload.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>${commons-logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
@@ -288,6 +161,26 @@
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<configLocation>checkstyle.xml</configLocation>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@@ -23,10 +23,10 @@ import java.util.Objects;
|
||||
* @author 六如
|
||||
*/
|
||||
public class RSATool {
|
||||
public static String RSA_ALGORITHM = "RSA";
|
||||
private static final String RSA_ALGORITHM = "RSA";
|
||||
|
||||
private KeyFormat keyFormat;
|
||||
private KeyLength keyLength;
|
||||
private final KeyFormat keyFormat;
|
||||
private final KeyLength keyLength;
|
||||
|
||||
public RSATool(KeyFormat keyFormat, KeyLength keyLength) {
|
||||
this.keyFormat = keyFormat;
|
||||
@@ -120,9 +120,9 @@ public class RSATool {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
// 模长
|
||||
int key_len = publicKey.getModulus().bitLength() / 8;
|
||||
int keyLen = publicKey.getModulus().bitLength() / 8;
|
||||
// 加密数据长度 <= 模长-11
|
||||
String[] datas = splitString(data, key_len - 11);
|
||||
String[] datas = splitString(data, keyLen - 11);
|
||||
String mi = "";
|
||||
// 如果明文长度大于模长-11则要分组加密
|
||||
for (String s : datas) {
|
||||
@@ -147,9 +147,9 @@ public class RSATool {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
// 模长
|
||||
int key_len = privateKey.getModulus().bitLength() / 8;
|
||||
int keyLen = privateKey.getModulus().bitLength() / 8;
|
||||
// 加密数据长度 <= 模长-11
|
||||
String[] datas = splitString(data, key_len - 11);
|
||||
String[] datas = splitString(data, keyLen - 11);
|
||||
String mi = "";
|
||||
// 如果明文长度大于模长-11则要分组加密
|
||||
for (String s : datas) {
|
||||
@@ -174,12 +174,12 @@ public class RSATool {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
// 模长
|
||||
int key_len = privateKey.getModulus().bitLength() / 8;
|
||||
int keyLen = privateKey.getModulus().bitLength() / 8;
|
||||
byte[] bytes = data.getBytes();
|
||||
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
|
||||
byte[] bcd = asciiToBcd(bytes, bytes.length);
|
||||
// 如果密文长度大于模长则要分组解密
|
||||
String ming = "";
|
||||
byte[][] arrays = splitArray(bcd, key_len);
|
||||
byte[][] arrays = splitArray(bcd, keyLen);
|
||||
for (byte[] arr : arrays) {
|
||||
ming += new String(cipher.doFinal(arr));
|
||||
}
|
||||
@@ -198,19 +198,19 @@ public class RSATool {
|
||||
Cipher cipher = Cipher.getInstance(keyFormat.getCipherAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
|
||||
// 模长
|
||||
int key_len = rsaPublicKey.getModulus().bitLength() / 8;
|
||||
int keyLen = rsaPublicKey.getModulus().bitLength() / 8;
|
||||
byte[] bytes = data.getBytes();
|
||||
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
|
||||
byte[] bcd = asciiToBcd(bytes, bytes.length);
|
||||
// 如果密文长度大于模长则要分组解密
|
||||
String ming = "";
|
||||
byte[][] arrays = splitArray(bcd, key_len);
|
||||
byte[][] arrays = splitArray(bcd, keyLen);
|
||||
for (byte[] arr : arrays) {
|
||||
ming += new String(cipher.doFinal(arr));
|
||||
}
|
||||
return ming;
|
||||
}
|
||||
|
||||
public static String convertPkcs8ToPkcs1(byte[] privateKeyData) throws Exception{
|
||||
public static String convertPkcs8ToPkcs1(byte[] privateKeyData) throws Exception {
|
||||
PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privateKeyData);
|
||||
ASN1Encodable encodable = pkInfo.parsePrivateKey();
|
||||
ASN1Primitive primitive = encodable.toASN1Primitive();
|
||||
@@ -222,17 +222,17 @@ public class RSATool {
|
||||
/**
|
||||
* ASCII码转BCD码
|
||||
*/
|
||||
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
|
||||
public static byte[] asciiToBcd(byte[] ascii, int asc_len) {
|
||||
byte[] bcd = new byte[asc_len / 2];
|
||||
int j = 0;
|
||||
for (int i = 0; i < (asc_len + 1) / 2; i++) {
|
||||
bcd[i] = asc_to_bcd(ascii[j++]);
|
||||
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++]) & 0xff) + (bcd[i] << 4));
|
||||
bcd[i] = ascToBcd(ascii[j++]);
|
||||
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : ascToBcd(ascii[j++]) & 0xff) + (bcd[i] << 4));
|
||||
}
|
||||
return bcd;
|
||||
}
|
||||
|
||||
public static byte asc_to_bcd(byte asc) {
|
||||
public static byte ascToBcd(byte asc) {
|
||||
byte bcd;
|
||||
|
||||
if ((asc >= '0') && (asc <= '9')) {
|
||||
@@ -380,47 +380,4 @@ public class RSATool {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------ Test ------------
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
RSATool rsa_pkcs8_1024 = new RSATool(KeyFormat.PKCS8, KeyLength.LENGTH_1024);
|
||||
RSATool rsa_pkcs8_2048 = new RSATool(KeyFormat.PKCS8, KeyLength.LENGTH_2048);
|
||||
|
||||
doTest(rsa_pkcs8_1024);
|
||||
doTest(rsa_pkcs8_2048);
|
||||
|
||||
// PKCS在Java环境无法测试,可以生成一对,到非java平台测试,如C#
|
||||
}
|
||||
|
||||
private static void doTest(RSATool rsaTool) throws Exception {
|
||||
System.out.println("秘钥格式:" + rsaTool.keyFormat.name() + ", 秘钥长度:" + rsaTool.keyLength.getLength());
|
||||
KeyStore keys = rsaTool.createKeys();
|
||||
String pubKey = keys.getPublicKey();
|
||||
System.out.println("pubKey:");
|
||||
System.out.println(pubKey);
|
||||
String priKey = keys.getPrivateKey();
|
||||
System.out.println("priKey:");
|
||||
System.out.println(priKey);
|
||||
System.out.println("--------");
|
||||
|
||||
String ming = "你好,abc123~!@=";
|
||||
// 用公钥加密
|
||||
String mi = rsaTool.encryptByPublicKey(ming, rsaTool.getPublicKey(pubKey));
|
||||
System.out.println("mi : " + mi);
|
||||
// 用私钥解密
|
||||
String ming2 = rsaTool.decryptByPrivateKey(mi, rsaTool.getPrivateKey(priKey));
|
||||
System.out.println("ming : " + ming2 + ", 结果:" + ming2.equals(ming));
|
||||
|
||||
// 用私钥加密
|
||||
String mi2 = rsaTool.encryptByPrivateKey(ming, rsaTool.getPrivateKey(priKey));
|
||||
|
||||
System.out.println("mi2 : " + mi2);
|
||||
// 用公钥解密
|
||||
String ming3 = rsaTool.decryptByPublicKey(mi2, rsaTool.getPublicKey(pubKey));
|
||||
System.out.println("ming3 : " + ming3 + ", 结果:" + ming3.equals(ming));
|
||||
System.out.println("---------------------");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
@@ -9,10 +9,9 @@ import java.util.Objects;
|
||||
*/
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
DISABLED((byte)2),
|
||||
ENABLE((byte)1),
|
||||
SET_PWD((byte)3),
|
||||
;
|
||||
DISABLED((byte) 2),
|
||||
ENABLE((byte) 1),
|
||||
SET_PWD((byte) 3);
|
||||
|
||||
private final int status;
|
||||
|
||||
|
@@ -9,8 +9,7 @@ public enum ErrorCode {
|
||||
JWT_CREATE("1000", "create token error"),
|
||||
JWT_ERROR("1000", "invalid token"),
|
||||
JWT_EXPIRED("1000", "token expired"),
|
||||
SET_PASSWORD("2000", "set password"),
|
||||
;
|
||||
SET_PASSWORD("2000", "set password");
|
||||
|
||||
ErrorCode(String code, String msg) {
|
||||
this.code = code;
|
||||
|
@@ -5,6 +5,7 @@ import lombok.Data;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @param <T> 数据
|
||||
* @author thc
|
||||
*/
|
||||
@Data
|
||||
|
@@ -3,11 +3,9 @@ package com.gitee.sop.adminbackend.service.isv;
|
||||
import com.gitee.fastmybatis.core.PageInfo;
|
||||
import com.gitee.fastmybatis.core.query.LambdaQuery;
|
||||
import com.gitee.fastmybatis.core.support.LambdaService;
|
||||
import com.gitee.sop.adminbackend.common.SpringContext;
|
||||
import com.gitee.sop.adminbackend.dao.entity.PermIsvGroup;
|
||||
import com.gitee.sop.adminbackend.dao.mapper.PermIsvGroupMapper;
|
||||
import com.gitee.sop.adminbackend.service.isv.dto.IsvGroupSettingDTO;
|
||||
import com.gitee.sop.adminbackend.service.isv.event.ChangeIsvPermEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -15,7 +13,6 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@@ -54,10 +54,9 @@ public class LoginService {
|
||||
case LDAP:
|
||||
// LDAP登录
|
||||
throw new UnsupportedOperationException("LDAP登录登录暂未支持");
|
||||
default: {
|
||||
default:
|
||||
// 默认注册账号登录
|
||||
userInfo = this.doDatabaseLogin(username, password);
|
||||
}
|
||||
}
|
||||
LoginUser loginUser = buildLoginUser(userInfo);
|
||||
// 保存到缓存
|
||||
|
@@ -14,8 +14,7 @@ public enum RegTypeEnum {
|
||||
BACKEND("backend"),
|
||||
FORM("form"),
|
||||
OAUTH("oauth"),
|
||||
LDAP("ldap"),
|
||||
;
|
||||
LDAP("ldap");
|
||||
|
||||
public static RegTypeEnum of(String source) {
|
||||
for (RegTypeEnum value : RegTypeEnum.values()) {
|
||||
|
@@ -3,169 +3,191 @@ package com.gitee.sop.adminbackend.util;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IdGen {
|
||||
private static long workId = 0;
|
||||
private static final SnowflakeIdWorker worker = new SnowflakeIdWorker(workId++, 0);
|
||||
private static long workId = 0;
|
||||
private static final SnowflakeIdWorker SNOWFLAKE_ID_WORKER = new SnowflakeIdWorker(workId++, 0);
|
||||
|
||||
public static long genId() {
|
||||
return worker.nextId();
|
||||
}
|
||||
public static long genId() {
|
||||
return SNOWFLAKE_ID_WORKER.nextId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一id
|
||||
* @return
|
||||
*/
|
||||
public static String nextId() {
|
||||
return String.valueOf(genId());
|
||||
}
|
||||
/**
|
||||
* 生成唯一id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String nextId() {
|
||||
return String.valueOf(genId());
|
||||
}
|
||||
|
||||
public static String uuid() {
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
public static String uuid() {
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Twitter_Snowflake<br>
|
||||
* SnowFlake的结构如下(每部分用-分开):<br>
|
||||
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
|
||||
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
|
||||
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
|
||||
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
|
||||
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
|
||||
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
|
||||
* 加起来刚好64位,为一个Long型。<br>
|
||||
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
|
||||
*/
|
||||
public static class SnowflakeIdWorker {
|
||||
/**
|
||||
* Twitter_Snowflake<br>
|
||||
* SnowFlake的结构如下(每部分用-分开):<br>
|
||||
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
|
||||
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
|
||||
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
|
||||
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
|
||||
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
|
||||
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
|
||||
* 加起来刚好64位,为一个Long型。<br>
|
||||
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
|
||||
*/
|
||||
public static class SnowflakeIdWorker {
|
||||
|
||||
// ==============================Fields===========================================
|
||||
/** 开始时间截 (2015-01-01) */
|
||||
private final long twepoch = 1420041100000L;
|
||||
// ==============================Fields===========================================
|
||||
/**
|
||||
* 开始时间截 (2015-01-01)
|
||||
*/
|
||||
private final long twepoch = 1420041100000L;
|
||||
|
||||
/** 机器id所占的位数 */
|
||||
private final long workerIdBits = 5L;
|
||||
/**
|
||||
* 机器id所占的位数
|
||||
*/
|
||||
private final long workerIdBits = 5L;
|
||||
|
||||
/** 数据标识id所占的位数 */
|
||||
private final long datacenterIdBits = 5L;
|
||||
/**
|
||||
* 数据标识id所占的位数
|
||||
*/
|
||||
private final long datacenterIdBits = 5L;
|
||||
|
||||
/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
|
||||
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
/**
|
||||
* 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
|
||||
*/
|
||||
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
|
||||
/** 支持的最大数据标识id,结果是31 */
|
||||
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
|
||||
/**
|
||||
* 支持的最大数据标识id,结果是31
|
||||
*/
|
||||
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
|
||||
|
||||
/** 序列在id中占的位数 */
|
||||
private final long sequenceBits = 12L;
|
||||
/**
|
||||
* 序列在id中占的位数
|
||||
*/
|
||||
private final long sequenceBits = 12L;
|
||||
|
||||
/** 机器ID向左移12位 */
|
||||
private final long workerIdShift = sequenceBits;
|
||||
/**
|
||||
* 机器ID向左移12位
|
||||
*/
|
||||
private final long workerIdShift = sequenceBits;
|
||||
|
||||
/** 数据标识id向左移17位(12+5) */
|
||||
private final long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
/**
|
||||
* 数据标识id向左移17位(12+5)
|
||||
*/
|
||||
private final long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
|
||||
/** 时间截向左移22位(5+5+12) */
|
||||
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
/**
|
||||
* 时间截向左移22位(5+5+12)
|
||||
*/
|
||||
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
|
||||
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
/**
|
||||
* 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
|
||||
*/
|
||||
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
|
||||
/** 工作机器ID(0~31) */
|
||||
private long workerId;
|
||||
/**
|
||||
* 工作机器ID(0~31)
|
||||
*/
|
||||
private long workerId;
|
||||
|
||||
/** 数据中心ID(0~31) */
|
||||
private long datacenterId;
|
||||
/**
|
||||
* 数据中心ID(0~31)
|
||||
*/
|
||||
private long datacenterId;
|
||||
|
||||
/** 毫秒内序列(0~4095) */
|
||||
private long sequence = 0L;
|
||||
/**
|
||||
* 毫秒内序列(0~4095)
|
||||
*/
|
||||
private long sequence = 0L;
|
||||
|
||||
/** 上次生成ID的时间截 */
|
||||
private long lastTimestamp = -1L;
|
||||
/**
|
||||
* 上次生成ID的时间截
|
||||
*/
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
//==============================Constructors=====================================
|
||||
/**
|
||||
* 构造函数
|
||||
* @param workerId 工作ID (0~31)
|
||||
* @param datacenterId 数据中心ID (0~31)
|
||||
*/
|
||||
public SnowflakeIdWorker(long workerId, long datacenterId) {
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
||||
}
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
|
||||
}
|
||||
this.workerId = workerId;
|
||||
this.datacenterId = datacenterId;
|
||||
}
|
||||
//==============================Constructors=====================================
|
||||
|
||||
// ==============================Methods==========================================
|
||||
/**
|
||||
* 获得下一个ID (该方法是线程安全的)
|
||||
* @return SnowflakeId
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
long timestamp = timeGen();
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param workerId 工作ID (0~31)
|
||||
* @param datacenterId 数据中心ID (0~31)
|
||||
*/
|
||||
public SnowflakeIdWorker(long workerId, long datacenterId) {
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
||||
}
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
|
||||
}
|
||||
this.workerId = workerId;
|
||||
this.datacenterId = datacenterId;
|
||||
}
|
||||
|
||||
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
if (timestamp < lastTimestamp) {
|
||||
throw new RuntimeException(
|
||||
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
|
||||
}
|
||||
// ==============================Methods==========================================
|
||||
|
||||
//如果是同一时间生成的,则进行毫秒内序列
|
||||
if (lastTimestamp == timestamp) {
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
//毫秒内序列溢出
|
||||
if (sequence == 0) {
|
||||
//阻塞到下一个毫秒,获得新的时间戳
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
}
|
||||
//时间戳改变,毫秒内序列重置
|
||||
else {
|
||||
sequence = 0L;
|
||||
}
|
||||
/**
|
||||
* 获得下一个ID (该方法是线程安全的)
|
||||
*
|
||||
* @return SnowflakeId
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
long timestamp = timeGen();
|
||||
|
||||
//上次生成ID的时间截
|
||||
lastTimestamp = timestamp;
|
||||
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
if (timestamp < lastTimestamp) {
|
||||
throw new RuntimeException(
|
||||
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
|
||||
}
|
||||
|
||||
//移位并通过或运算拼到一起组成64位的ID
|
||||
return ((timestamp - twepoch) << timestampLeftShift)
|
||||
| (datacenterId << datacenterIdShift)
|
||||
| (workerId << workerIdShift)
|
||||
| sequence;
|
||||
}
|
||||
//如果是同一时间生成的,则进行毫秒内序列
|
||||
if (lastTimestamp == timestamp) {
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
//毫秒内序列溢出
|
||||
if (sequence == 0) {
|
||||
//阻塞到下一个毫秒,获得新的时间戳
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
//时间戳改变,毫秒内序列重置
|
||||
sequence = 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻塞到下一个毫秒,直到获得新的时间戳
|
||||
* @param lastTimestamp 上次生成ID的时间截
|
||||
* @return 当前时间戳
|
||||
*/
|
||||
protected long tilNextMillis(long lastTimestamp) {
|
||||
long timestamp = timeGen();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
//上次生成ID的时间截
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
/**
|
||||
* 返回以毫秒为单位的当前时间
|
||||
* @return 当前时间(毫秒)
|
||||
*/
|
||||
protected long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
//移位并通过或运算拼到一起组成64位的ID
|
||||
return ((timestamp - twepoch) << timestampLeftShift)
|
||||
| (datacenterId << datacenterIdShift)
|
||||
| (workerId << workerIdShift)
|
||||
| sequence;
|
||||
}
|
||||
|
||||
}
|
||||
/*//==============================Test=============================================
|
||||
*/
|
||||
/** 测试
|
||||
public static void main(String[] args) {
|
||||
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
long id = idWorker.nextId();
|
||||
System.out.println("id:" + id);
|
||||
System.out.println("toBinaryString:" + Long.toBinaryString(id));
|
||||
}
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* 阻塞到下一个毫秒,直到获得新的时间戳
|
||||
*
|
||||
* @param lastTimestamp 上次生成ID的时间截
|
||||
* @return 当前时间戳
|
||||
*/
|
||||
protected long tilNextMillis(long lastTimestamp) {
|
||||
long timestamp = timeGen();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回以毫秒为单位的当前时间
|
||||
*
|
||||
* @return 当前时间(毫秒)
|
||||
*/
|
||||
protected long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ import java.util.Set;
|
||||
@Slf4j
|
||||
public class JwtUtil {
|
||||
|
||||
private static final Map<String, Object> headerClaims = new HashMap<>();
|
||||
private static final Map<String, Object> HEADER_CLAIMS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 登录成功后跳转页面
|
||||
@@ -39,12 +39,12 @@ public class JwtUtil {
|
||||
));
|
||||
|
||||
static {
|
||||
headerClaims.put("typ", "JWT");
|
||||
headerClaims.put("alg", "HS256");
|
||||
HEADER_CLAIMS.put("typ", "JWT");
|
||||
HEADER_CLAIMS.put("alg", "HS256");
|
||||
}
|
||||
|
||||
public static String createJwt(Map<String, String> data, int timeoutDays, String secret) {
|
||||
JWTCreator.Builder builder = JWT.create().withHeader(headerClaims);
|
||||
JWTCreator.Builder builder = JWT.create().withHeader(HEADER_CLAIMS);
|
||||
Set<Map.Entry<String, String>> entrySet = data.entrySet();
|
||||
for (Map.Entry<String, String> entry : entrySet) {
|
||||
builder.withClaim(entry.getKey(), entry.getValue());
|
||||
|
@@ -25,13 +25,9 @@ public class PasswordUtil {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String password = getRandomPassword(32);
|
||||
System.out.println(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机密码生成,仅字母数字
|
||||
*
|
||||
* @param len 密码长度,必须大于等于4
|
||||
*/
|
||||
public static String getRandomSimplePassword(int len) {
|
||||
@@ -48,6 +44,7 @@ public class PasswordUtil {
|
||||
|
||||
/**
|
||||
* 随机密码生成
|
||||
*
|
||||
* @param len 密码长度,必须大于等于6
|
||||
*/
|
||||
public static String getRandomPassword(int len) {
|
||||
|
Reference in New Issue
Block a user