new
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
*.iml
|
||||
target
|
||||
logs
|
||||
70
common/pom.xml
Normal file
70
common/pom.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>security-api-demo</artifactId>
|
||||
<groupId>org.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>common</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!--lombok-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.10</version>
|
||||
</dependency>
|
||||
<!--commons-langs-->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.11</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<!--json-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.73</version>
|
||||
</dependency>
|
||||
<!-- JWT -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.15</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
<!--日志-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
16
common/src/main/java/com/demo/constant/RSAConstant.java
Normal file
16
common/src/main/java/com/demo/constant/RSAConstant.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.demo.constant;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Rosh
|
||||
* @Date: 2021/10/27 09:53
|
||||
*/
|
||||
public final class RSAConstant {
|
||||
|
||||
private RSAConstant(){
|
||||
|
||||
}
|
||||
public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFtTlL61IqIGd+fRLUhJ0MjsqFXFJswCohJ45m51WvbxDPRP3gllW0WChk74D5JEOpMDSWo4C7RfoGlBRNW7kQ6qYGukYZ5jgYpzoT0+gp3on96fQXEyQJysv9xiTPIdmSXXVVj1HAOJw29RbzxIVKUSzzPXvEtXRTtCC1+wkAJQIDAQAB";
|
||||
|
||||
public static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIW1OUvrUiogZ359EtSEnQyOyoVcUmzAKiEnjmbnVa9vEM9E/eCWVbRYKGTvgPkkQ6kwNJajgLtF+gaUFE1buRDqpga6RhnmOBinOhPT6Cneif3p9BcTJAnKy/3GJM8h2ZJddVWPUcA4nDb1FvPEhUpRLPM9e8S1dFO0ILX7CQAlAgMBAAECgYBC4amtbiKFa/wY61tV7pfYRjzLhKi+OUlZmD3E/4Z+4KGZ7DrJ8qkgMtDR3HO5LAikQrare1HTW2d7juqw32ascu+uDObf4yrYNKin+ZDLUYvIDfLhThPxnZJwQ/trdtfxO3VM//XbwZacmwYbAsYW/3QPUXwwOPAgbC2oth8kqQJBANKLyXcdjZx4cwJVl7xNeC847su8y6bPpcBASsaQloCIPiNBIg1h76dpfEGIQBYWJWbBsxtHe/MhOmz7fNFDS2sCQQCiktYZR0dZNH4eNX329LoRuBiltpr9tf36rVOlKr1GSHkLYEHF2qtyXV2mdrY8ZWpvuo3qm1oSLaqmop2rN9avAkBHk85B+IIUF77BpGeZVJzvMOO9z8lMRHuNCE5jgvQnbinxwkrZUdovh+T+QlvHJnBApslFFOBGn51FP5oHamFRAkEAmwZmPsinkrrpoKjlqz6GyCrC5hKRDWoj/IyXfKKaxpCJTH3HeoIghvfdO8Vr1X/n1Q8SESt+4mLFngznSMQAZQJBAJx07bCFYbA2IocfFV5LTEYTIiUeKdue2NP2yWqZ/+tB5H7jNwQTJmX1mn0W/sZm4+nJM7SjfETpNZhH49+rV6U=";
|
||||
}
|
||||
13
common/src/main/java/com/demo/constant/UserConstant.java
Normal file
13
common/src/main/java/com/demo/constant/UserConstant.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.demo.constant;
|
||||
|
||||
public class UserConstant {
|
||||
|
||||
private UserConstant() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final String TOKEN = "token";
|
||||
|
||||
|
||||
}
|
||||
22
common/src/main/java/com/demo/excepiton/RSAException.java
Normal file
22
common/src/main/java/com/demo/excepiton/RSAException.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.demo.excepiton;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Rosh
|
||||
* @Date: 2021/8/10 17:39
|
||||
*/
|
||||
@Getter
|
||||
public class RSAException extends RuntimeException {
|
||||
|
||||
private final String message;
|
||||
|
||||
|
||||
public RSAException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
88
common/src/main/java/com/demo/utils/RSAUtils.java
Normal file
88
common/src/main/java/com/demo/utils/RSAUtils.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package com.demo.utils;
|
||||
|
||||
import com.demo.excepiton.RSAException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class RSAUtils {
|
||||
|
||||
public static final String PUBLIC_KEY = "public_key";
|
||||
|
||||
public static final String PRIVATE_KEY = "private_key";
|
||||
|
||||
|
||||
public static Map<String, String> generateRasKey() {
|
||||
Map<String, String> rs = new HashMap<>();
|
||||
try {
|
||||
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
|
||||
KeyPairGenerator keyPairGen = null;
|
||||
keyPairGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGen.initialize(1024, new SecureRandom());
|
||||
// 生成一个密钥对,保存在keyPair中
|
||||
KeyPair keyPair = keyPairGen.generateKeyPair();
|
||||
// 得到私钥 公钥
|
||||
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
|
||||
// 得到私钥字符串
|
||||
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
|
||||
// 将公钥和私钥保存到Map
|
||||
rs.put(PUBLIC_KEY, publicKeyString);
|
||||
rs.put(PRIVATE_KEY, privateKeyString);
|
||||
} catch (Exception e) {
|
||||
throw new RSAException("RsaUtils invoke genKeyPair failed.");
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
|
||||
public static String encrypt(String str, String publicKey) {
|
||||
try {
|
||||
//base64编码的公钥
|
||||
byte[] decoded = Base64.decodeBase64(publicKey);
|
||||
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
|
||||
//RSA加密
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
|
||||
return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (Exception e) {
|
||||
throw new RSAException("RsaUtils invoke encrypt failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String decrypt(String str, String privateKey) {
|
||||
|
||||
try {
|
||||
//64位解码加密后的字符串
|
||||
byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
|
||||
//base64编码的私钥
|
||||
byte[] decoded = Base64.decodeBase64(privateKey);
|
||||
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
|
||||
//RSA解密
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, priKey);
|
||||
return new String(cipher.doFinal(inputByte));
|
||||
} catch (Exception e) {
|
||||
throw new RSAException("RsaUtils invoke decrypt failed.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
75
common/src/main/java/com/demo/utils/TokenUtils.java
Normal file
75
common/src/main/java/com/demo/utils/TokenUtils.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.demo.utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.JwtBuilder;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Rosh
|
||||
* @Date: 2021/8/11 14:21
|
||||
*/
|
||||
public final class TokenUtils {
|
||||
|
||||
|
||||
private static final String SIGN_KEY = "STREAM_TOKEN";
|
||||
|
||||
|
||||
/**
|
||||
*jwt 有效期为3天
|
||||
*/
|
||||
private static final Long JWT_EXPIRE_TIME_LONG = 1000 * 60 * 60 * 24 * 3L;
|
||||
|
||||
|
||||
private TokenUtils() {
|
||||
|
||||
}
|
||||
|
||||
public static String createToken(String str) {
|
||||
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
||||
long nowMillis = System.currentTimeMillis();
|
||||
Date now = new Date(nowMillis);
|
||||
SecretKey secretKey = createSecretKey();
|
||||
|
||||
JwtBuilder builder = Jwts.builder()
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.setIssuedAt(now)
|
||||
.setSubject(str)
|
||||
.signWith(signatureAlgorithm, secretKey);
|
||||
|
||||
long expMillis = System.currentTimeMillis() + JWT_EXPIRE_TIME_LONG;
|
||||
Date exp = new Date(expMillis);
|
||||
|
||||
//token过期时间
|
||||
builder.setExpiration(exp);
|
||||
|
||||
return builder.compact();
|
||||
}
|
||||
|
||||
private static SecretKey createSecretKey() {
|
||||
byte[] encodedKey = Base64.decodeBase64(SIGN_KEY);
|
||||
return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
|
||||
}
|
||||
|
||||
|
||||
public static Claims getClaim(String token) {
|
||||
SecretKey secretKey = createSecretKey();
|
||||
try {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(secretKey)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
105
common/src/test/java/com/common/RSAEncrypt.java
Normal file
105
common/src/test/java/com/common/RSAEncrypt.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package com.common;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import javax.crypto.Cipher;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RSAEncrypt {
|
||||
private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用于封装随机产生的公钥与私钥
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("username", "rosh");
|
||||
jsonObject.put("password", "123456");
|
||||
|
||||
//生成公钥和私钥
|
||||
genKeyPair();
|
||||
//加密字符串
|
||||
String message = jsonObject.toJSONString();
|
||||
System.out.println("随机生成的公钥为:" + keyMap.get(0));
|
||||
System.out.println("随机生成的私钥为:" + keyMap.get(1));
|
||||
String messageEn = encrypt(message,keyMap.get(0));
|
||||
System.out.println(message + "\t加密后的字符串为:" + messageEn);
|
||||
String messageDe = decrypt(messageEn,keyMap.get(1));
|
||||
System.out.println("还原后的字符串为:" + messageDe);
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机生成密钥对
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static void genKeyPair() throws NoSuchAlgorithmException {
|
||||
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
|
||||
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
|
||||
// 初始化密钥对生成器,密钥大小为96-1024位
|
||||
keyPairGen.initialize(1024,new SecureRandom());
|
||||
// 生成一个密钥对,保存在keyPair中
|
||||
KeyPair keyPair = keyPairGen.generateKeyPair();
|
||||
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
|
||||
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
|
||||
// 得到私钥字符串
|
||||
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
|
||||
// 将公钥和私钥保存到Map
|
||||
keyMap.put(0,publicKeyString); //0表示公钥
|
||||
keyMap.put(1,privateKeyString); //1表示私钥
|
||||
}
|
||||
/**
|
||||
* RSA公钥加密
|
||||
*
|
||||
* @param str
|
||||
* 加密字符串
|
||||
* @param publicKey
|
||||
* 公钥
|
||||
* @return 密文
|
||||
* @throws Exception
|
||||
* 加密过程中的异常信息
|
||||
*/
|
||||
public static String encrypt( String str, String publicKey ) throws Exception{
|
||||
//base64编码的公钥
|
||||
byte[] decoded = Base64.decodeBase64(publicKey);
|
||||
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
|
||||
//RSA加密
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
|
||||
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
|
||||
return outStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA私钥解密
|
||||
*
|
||||
* @param str
|
||||
* 加密字符串
|
||||
* @param privateKey
|
||||
* 私钥
|
||||
* @return 铭文
|
||||
* @throws Exception
|
||||
* 解密过程中的异常信息
|
||||
*/
|
||||
public static String decrypt(String str, String privateKey) throws Exception{
|
||||
//64位解码加密后的字符串
|
||||
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
|
||||
//base64编码的私钥
|
||||
byte[] decoded = Base64.decodeBase64(privateKey);
|
||||
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
|
||||
//RSA解密
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, priKey);
|
||||
String outStr = new String(cipher.doFinal(inputByte));
|
||||
return outStr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
common/src/test/java/com/common/test.java
Normal file
12
common/src/test/java/com/common/test.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.common;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/25 23:32
|
||||
*/
|
||||
public class test {
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
62
gateway/pom.xml
Normal file
62
gateway/pom.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>security-api-demo</artifactId>
|
||||
<groupId>org.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>gateway</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
</dependency>
|
||||
<!--spring cloud alibaba-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!--日志-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--依赖common-->
|
||||
<dependency>
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 添加spring boot 的依赖 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<configuration>
|
||||
<mainClass>com.demo.gateway.GatewayApplication</mainClass>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.demo.gateway;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/24 23:34
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
public class GatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(GatewayApplication.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.demo.gateway.config;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Rosh
|
||||
* @Date: 2021/10/27 09:35
|
||||
*/
|
||||
public final class FilterUtils {
|
||||
|
||||
private FilterUtils() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Mono<Void> invalidToken(ServerWebExchange exchange) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", HttpStatus.UNAUTHORIZED.value());
|
||||
json.put("msg", "无效的token");
|
||||
return buildReturnMono(json, exchange);
|
||||
}
|
||||
|
||||
public static Mono<Void> invalidUrl(ServerWebExchange exchange){
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
json.put("msg", "无效的请求");
|
||||
return buildReturnMono(json, exchange);
|
||||
}
|
||||
|
||||
|
||||
public static Mono<Void> buildReturnMono(JSONObject json, ServerWebExchange exchange) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
byte[] bits = json.toJSONString().getBytes(StandardCharsets.UTF_8);
|
||||
DataBuffer buffer = response.bufferFactory().wrap(bits);
|
||||
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
//指定编码,否则在浏览器中会中文乱码
|
||||
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.demo.gateway.config;
|
||||
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.reactive.CorsWebFilter;
|
||||
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
||||
|
||||
@Configuration
|
||||
public class GatewayCrosConfiguration {
|
||||
|
||||
@Bean
|
||||
public CorsWebFilter corsWebFilter() {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.addAllowedHeader("*");
|
||||
corsConfiguration.addAllowedMethod("*");
|
||||
corsConfiguration.addAllowedOrigin("*");
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", corsConfiguration);
|
||||
return new CorsWebFilter(source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.demo.gateway.exception;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.demo.excepiton.RSAException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
|
||||
public abstract class AbstractExceptionHandler {
|
||||
|
||||
|
||||
protected JSONObject buildErrorMap(Throwable ex) {
|
||||
JSONObject json = new JSONObject();
|
||||
if (ex instanceof RSAException || ex instanceof IllegalArgumentException) {
|
||||
json.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
if (StringUtils.isNotBlank(ex.getMessage())){
|
||||
json.put("msg", ex.getMessage());
|
||||
}else {
|
||||
json.put("msg", "无效的请求");
|
||||
}
|
||||
|
||||
} else {
|
||||
json.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
json.put("msg", "未知错误联系管理员");
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.demo.gateway.exception;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class GatewayExceptionConfig {
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public ErrorWebExceptionHandler errorWebExceptionHandler(ObjectProvider<List<ViewResolver>> viewResolversProvider,
|
||||
ServerCodecConfigurer serverCodecConfigurer) {
|
||||
GatewayExceptionHandler gatewayExceptionHandler = new GatewayExceptionHandler();
|
||||
gatewayExceptionHandler.setViewResolvers(viewResolversProvider.getIfAvailable(Collections::emptyList));
|
||||
gatewayExceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
|
||||
gatewayExceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
|
||||
return gatewayExceptionHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.demo.gateway.exception;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.codec.HttpMessageWriter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class GatewayExceptionHandler extends AbstractExceptionHandler implements ErrorWebExceptionHandler {
|
||||
|
||||
|
||||
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();
|
||||
|
||||
|
||||
private List<HttpMessageWriter<?>> messageWriters = Collections.emptyList();
|
||||
|
||||
|
||||
private List<ViewResolver> viewResolvers = Collections.emptyList();
|
||||
|
||||
|
||||
private ThreadLocal<JSONObject> exceptionHandlerResult = new ThreadLocal<>();
|
||||
|
||||
|
||||
public void setMessageReaders(List<HttpMessageReader<?>> messageReaders) {
|
||||
Assert.notNull(messageReaders, "'messageReaders' must not be null");
|
||||
this.messageReaders = messageReaders;
|
||||
}
|
||||
|
||||
|
||||
public void setViewResolvers(List<ViewResolver> viewResolvers) {
|
||||
this.viewResolvers = viewResolvers;
|
||||
}
|
||||
|
||||
|
||||
public void setMessageWriters(List<HttpMessageWriter<?>> messageWriters) {
|
||||
Assert.notNull(messageWriters, "'messageWriters' must not be null");
|
||||
this.messageWriters = messageWriters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
|
||||
JSONObject errorInfo = super.buildErrorMap(ex);
|
||||
if (exchange.getResponse().isCommitted()) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
exceptionHandlerResult.set(errorInfo);
|
||||
ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders);
|
||||
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest)
|
||||
.switchIfEmpty(Mono.error(ex))
|
||||
.flatMap(handler -> handler.handle(newRequest))
|
||||
.flatMap(response -> write(exchange, response));
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
|
||||
Map<String, Object> result = exceptionHandlerResult.get();
|
||||
return ServerResponse.status(HttpStatus.OK)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(BodyInserters.fromValue(result));
|
||||
}
|
||||
|
||||
|
||||
private Mono<? extends Void> write(ServerWebExchange exchange,
|
||||
ServerResponse response) {
|
||||
exchange.getResponse().getHeaders().setContentType(response.headers().getContentType());
|
||||
return response.writeTo(exchange, new ResponseContext());
|
||||
}
|
||||
|
||||
private class ResponseContext implements ServerResponse.Context {
|
||||
|
||||
@Override
|
||||
public List<HttpMessageWriter<?>> messageWriters() {
|
||||
return GatewayExceptionHandler.this.messageWriters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewResolver> viewResolvers() {
|
||||
return GatewayExceptionHandler.this.viewResolvers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package com.demo.gateway.filter;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.nacos.common.utils.Md5Utils;
|
||||
import com.demo.gateway.config.FilterUtils;
|
||||
import com.demo.gateway.pojo.MyCachedBodyOutputMessage;
|
||||
import com.demo.gateway.utils.AESUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.support.BodyInserterContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ReactiveHttpOutputMessage;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.reactive.function.BodyInserter;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.server.HandlerStrategies;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/26 22:24
|
||||
*/
|
||||
@Configuration
|
||||
@Component
|
||||
public class RequestEncryptionGlobalFilter implements GlobalFilter, Ordered {
|
||||
|
||||
private static final String AES_SECURTY = "MTIzNDU2Nzg5MTIzNDU2Nw==";
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
|
||||
private static final String ERROR_MESSAGE = "拒绝服务";
|
||||
private static final String SIGN_ERROR_MESSAGE = "签名过期";
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
//1 获取时间戳
|
||||
Long dateTimestamp = getDateTimestamp(exchange.getRequest().getHeaders());
|
||||
//2 获取RequestId
|
||||
String requestId = getRequestId(exchange.getRequest().getHeaders());
|
||||
//3 获取签名
|
||||
String sign = getSign(exchange.getRequest().getHeaders());
|
||||
//4 如果是登录不校验Token
|
||||
// String requestUrl = exchange.getRequest().getPath().value();
|
||||
// AntPathMatcher pathMatcher = new AntPathMatcher();
|
||||
// if (!pathMatcher.match("/user/login", requestUrl)) {
|
||||
// String token = exchange.getRequest().getHeaders().getFirst(UserConstant.TOKEN);
|
||||
// Claims claim = TokenUtils.getClaim(token);
|
||||
// if (StringUtils.isBlank(token) || claim == null) {
|
||||
// return FilterUtils.invalidToken(exchange);
|
||||
// }
|
||||
// }
|
||||
//5 修改请求参数,并获取请求参数
|
||||
Map<String, Object> paramMap;
|
||||
try {
|
||||
paramMap = updateRequestParam(exchange);
|
||||
} catch (Exception e) {
|
||||
return FilterUtils.invalidUrl(exchange);
|
||||
}
|
||||
//6 获取请求体,修改请求体
|
||||
ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
|
||||
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
|
||||
String encrypt = AESUtil.decrypt(body, AES_SECURTY);
|
||||
JSONObject jsonObject = JSON.parseObject(encrypt);
|
||||
for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
|
||||
paramMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
checkSign(sign, dateTimestamp, requestId, paramMap);
|
||||
return Mono.just(encrypt);
|
||||
});
|
||||
|
||||
//创建BodyInserter修改请求体
|
||||
|
||||
BodyInserter<Mono<String>, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.putAll(exchange.getRequest().getHeaders());
|
||||
headers.remove(HttpHeaders.CONTENT_LENGTH);
|
||||
//创建CachedBodyOutputMessage并且把请求param加入,初始化校验信息
|
||||
MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);
|
||||
|
||||
outputMessage.initial(paramMap, requestId, sign, dateTimestamp);
|
||||
|
||||
//修改响应体
|
||||
MyCachedBodyOutputMessage repOutputMessage = new MyCachedBodyOutputMessage(exchange, headers);
|
||||
repOutputMessage.getBody();
|
||||
|
||||
|
||||
return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
|
||||
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
Flux<DataBuffer> body = outputMessage.getBody();
|
||||
if (body.equals(Flux.empty())) {
|
||||
//验证签名
|
||||
checkSign(outputMessage.getSign(), outputMessage.getDateTimestamp(), outputMessage.getRequestId(), outputMessage.getParamMap());
|
||||
}
|
||||
return outputMessage.getBody();
|
||||
}
|
||||
};
|
||||
|
||||
return chain.filter(exchange.mutate().request(decorator).build());
|
||||
}));
|
||||
}
|
||||
|
||||
public void checkSign(String sign, Long dateTimestamp, String requestId, Map<String, Object> paramMap) {
|
||||
String str = JSON.toJSONString(paramMap) + requestId + dateTimestamp;
|
||||
String tempSign = Md5Utils.getMD5(str.getBytes());
|
||||
if (!tempSign.equals(sign)) {
|
||||
throw new IllegalArgumentException(SIGN_ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改前端传的参数
|
||||
*/
|
||||
private Map<String, Object> updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
URI uri = request.getURI();
|
||||
String query = uri.getQuery();
|
||||
if (StringUtils.isNotBlank(query) && query.contains("param")) {
|
||||
return getParamMap(query);
|
||||
}
|
||||
return new TreeMap<>();
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Object> getParamMap(String param) {
|
||||
Map<String, Object> map = new TreeMap<>();
|
||||
String[] split = param.split("&");
|
||||
for (String str : split) {
|
||||
String[] params = str.split("=");
|
||||
map.put(params[0], params[1]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private String getSign(HttpHeaders headers) {
|
||||
List<String> list = headers.get("sign");
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
private Long getDateTimestamp(HttpHeaders httpHeaders) {
|
||||
List<String> list = httpHeaders.get("timestamp");
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
long timestamp = Long.parseLong(list.get(0));
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
//有效时长为5分钟
|
||||
if (currentTimeMillis - timestamp > 1000 * 60 * 5) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private String getRequestId(HttpHeaders headers) {
|
||||
List<String> list = headers.get("requestId");
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
String requestId = list.get(0);
|
||||
//如果requestId存在redis中直接返回
|
||||
String temp = redisTemplate.opsForValue().get(requestId);
|
||||
if (StringUtils.isNotBlank(temp)) {
|
||||
throw new IllegalArgumentException("RequestId 非法");
|
||||
}
|
||||
redisTemplate.opsForValue().set(requestId, requestId, 5, TimeUnit.MINUTES);
|
||||
return requestId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 80;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.demo.gateway.filter;
|
||||
|
||||
import com.demo.gateway.utils.AESUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 响应 Body 加密 过滤器
|
||||
*
|
||||
* @author xuxiaowei
|
||||
* @see ServerHttpResponseDecorator
|
||||
* @since 0.0.1
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@Component
|
||||
public class ResponseEncryptionGlobalFilter implements GlobalFilter, Ordered {
|
||||
private static final String AES_SECURTY = "MTIzNDU2Nzg5MTIzNDU2Nw=="; //1234567891234567
|
||||
/**
|
||||
* 加密 过滤器 优先级
|
||||
* <p>
|
||||
* 响应数据过滤器优先级需要小于 0,否则将无效
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
log.debug("触发");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
|
||||
ServerHttpResponseDecorator decorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Mono<Void> writeWith(@NonNull Publisher<? extends DataBuffer> body) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Flux<? extends DataBuffer> fluxDataBuffer = (Flux<? extends DataBuffer>) body;
|
||||
return super.writeWith(fluxDataBuffer.buffer()
|
||||
.map(dataBuffer -> {
|
||||
DataBuffer join = exchange.getResponse().bufferFactory().join(dataBuffer);
|
||||
byte[] bytes = new byte[join.readableByteCount()];
|
||||
join.read(bytes);
|
||||
DataBufferUtils.release(join);
|
||||
|
||||
log.debug("加密前 body:{}", new String(bytes));
|
||||
|
||||
byte[] encryption;
|
||||
|
||||
try {
|
||||
//加密
|
||||
encryption = AESUtil.encrypt(new String(bytes), AES_SECURTY).getBytes();
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
encryption = bytes;
|
||||
log.error("数据类型不是 JSON,不加密", e);
|
||||
}
|
||||
|
||||
log.debug("加密后 body:{}", new String(encryption, StandardCharsets.UTF_8));
|
||||
|
||||
return exchange.getResponse().bufferFactory().wrap(encryption);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return chain.filter(exchange.mutate().response(decorator).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.demo.gateway.pojo;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: Rosh
|
||||
* @Date: 2021/10/27 11:03
|
||||
*/
|
||||
public class MyCachedBodyOutputMessage extends CachedBodyOutputMessage {
|
||||
|
||||
private Map<String, Object> paramMap;
|
||||
|
||||
private Long dateTimestamp;
|
||||
|
||||
private String requestId;
|
||||
|
||||
private String sign;
|
||||
|
||||
public MyCachedBodyOutputMessage(ServerWebExchange exchange, HttpHeaders httpHeaders) {
|
||||
super(exchange, httpHeaders);
|
||||
}
|
||||
|
||||
public void initial(Map<String, Object> paramMap, String requestId, String sign, Long dateTimestamp) {
|
||||
this.paramMap = paramMap;
|
||||
this.requestId = requestId;
|
||||
this.sign = sign;
|
||||
this.dateTimestamp = dateTimestamp;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getParamMap() {
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
public Long getDateTimestamp() {
|
||||
return dateTimestamp;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public String getSign() {
|
||||
return sign;
|
||||
}
|
||||
}
|
||||
12
gateway/src/main/java/com/demo/gateway/test.java
Normal file
12
gateway/src/main/java/com/demo/gateway/test.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.demo.gateway;
|
||||
|
||||
import com.demo.gateway.utils.AESUtil;
|
||||
|
||||
public class test {
|
||||
public static void main(String[] args) {
|
||||
String str = "uMDI+g2bagWZ6+wlwBGQYjPFu1pJ8oA39/HzrpZT7nbUDdZogctMTxiPY //vF2stkEFLwjhiJTlPZObyLKInxjIzojhVH3gIMVQ0mcbmp3fNbYVds8cN9jkSYxEgp1eWCXbPCDxKsTuXD6q671vlNGg2m7Qu/rW+2jelZWGYVse2KI6rLfkB54r23ZVHOU2gNEC6DYIvn2+vdtOe89pd7hM1XbRyBHYVjwM/0TTHrOU4k8d0oP5/vbmLHFUgYpXq4R4ZxsXa70+/w9xAjRU+THnItxiLx2HZgCros+F2I5uT0a4lBXtOZVUGYJe2PX08oi2ySmrgVrBYQhWX4z7/nW+0DCbBbOcT2rS9zWflFqUKOseKRRVrSE02Zk6+RgfX9yn/BTbhPjJezI9NdbZYQ==";
|
||||
//String encrypt = AESUtil.encrypt(str, "MTIzNDU2Nzg5MTIzNDU2Nw==");
|
||||
String decrypt = AESUtil.decrypt(str, "MTIzNDU2Nzg5MTIzNDU2Nw==");
|
||||
System.out.println(decrypt);
|
||||
}
|
||||
}
|
||||
57
gateway/src/main/java/com/demo/gateway/utils/AESUtil.java
Normal file
57
gateway/src/main/java/com/demo/gateway/utils/AESUtil.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.demo.gateway.utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
public class AESUtil {
|
||||
static String base64EncodedIV = "MTIzNDU2Nzg5MTIzNDU2Nw=="; //1234567891234567
|
||||
public static String decrypt(String encryptedText, String base64EncodedKey) {
|
||||
try {
|
||||
// 解码密钥
|
||||
|
||||
byte[] decodedKey = Base64.getDecoder().decode(base64EncodedKey);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(decodedKey, "AES");
|
||||
byte[] decodedIV = Base64.getDecoder().decode(base64EncodedIV);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(decodedIV);
|
||||
// 创建 AES 密码器
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
||||
|
||||
// 解密
|
||||
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
|
||||
|
||||
// 将解密后的字节数组转换为字符串并返回
|
||||
return new String(decryptedBytes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static String encrypt(String plainText, String base64EncodedKey) {
|
||||
try {
|
||||
// 解码密钥
|
||||
byte[] decodedKey = Base64.getDecoder().decode(base64EncodedKey);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(decodedKey, "AES");
|
||||
|
||||
byte[] decodedIV = Base64.getDecoder().decode(base64EncodedIV);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(decodedIV);
|
||||
|
||||
// 创建 AES 密码器
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
|
||||
|
||||
// 加密
|
||||
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
|
||||
|
||||
|
||||
// 将加密后的字节数组和 Base64 编码的初始化向量一起返回
|
||||
return Base64.getEncoder().encodeToString(encryptedBytes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
23
gateway/src/main/resources/application.yml
Normal file
23
gateway/src/main/resources/application.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
server:
|
||||
port: 9000
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: gateway-service
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 192.168.202.220:8848
|
||||
gateway:
|
||||
routes:
|
||||
- id: demo-one
|
||||
uri: lb://libirary-service
|
||||
predicates:
|
||||
- Path=/**
|
||||
# predicates:
|
||||
# - Path=/api/user/**
|
||||
# filters:
|
||||
# - RewritePath=/api/(?<segment>.*),/$\{segment}
|
||||
redis:
|
||||
port: 6379
|
||||
host: 127.0.0.1
|
||||
109
library/pom.xml
Normal file
109
library/pom.xml
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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.1</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>library</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>library</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.14.1</version> <!-- 版本号可以根据你的需求进行更改 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.14.1</version> <!-- 版本号可以根据你的需求进行更改 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.4.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.7.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.11.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.18.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>2021.0.4.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.6.1 </version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.library;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@MapperScan("com.example.library.mapper")
|
||||
public class LibraryApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LibraryApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
11
library/src/main/java/com/example/library/LoginUser.java
Normal file
11
library/src/main/java/com/example/library/LoginUser.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.example.library;
|
||||
public class LoginUser {
|
||||
private static int visitCount = 0;
|
||||
public static void addVisitCount() {
|
||||
LoginUser.visitCount++;
|
||||
}
|
||||
|
||||
public static int getVisitCount() {
|
||||
return LoginUser.visitCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.example.library.commom;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* mybatis-plus 分页插件
|
||||
*/
|
||||
@Configuration
|
||||
@MapperScan("com.example.demo.mapper")
|
||||
@MapperScan("com.example.demo.service")
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
}
|
||||
65
library/src/main/java/com/example/library/commom/Result.java
Normal file
65
library/src/main/java/com/example/library/commom/Result.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package com.example.library.commom;
|
||||
|
||||
public class Result<T> {
|
||||
private String code;
|
||||
private String msg;
|
||||
private T data;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
public Result(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static Result success() {
|
||||
Result result = new Result<>();
|
||||
result.setCode("0");
|
||||
result.setMsg("成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(T data) {
|
||||
Result<T> result = new Result<>(data);
|
||||
result.setCode("0");
|
||||
result.setMsg("成功");
|
||||
return result;
|
||||
}
|
||||
public static <T> Result<T> noAuth() {
|
||||
Result<T> result = new Result<>();
|
||||
result.setCode("401");
|
||||
result.setMsg("error");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error(String code, String msg) {
|
||||
Result result = new Result();
|
||||
result.setCode(code);
|
||||
result.setMsg(msg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.Book;
|
||||
import com.example.library.mapper.BookMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/book")
|
||||
public class BookController {
|
||||
@Resource
|
||||
BookMapper BookMapper;
|
||||
|
||||
@PostMapping
|
||||
public Result<?> save(@RequestBody Book Book){
|
||||
BookMapper.insert(Book);
|
||||
return Result.success();
|
||||
}
|
||||
@PutMapping
|
||||
public Result<?> update(@RequestBody Book Book){
|
||||
BookMapper.updateById(Book);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
@PostMapping("/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestBody List<Integer> ids){
|
||||
BookMapper.deleteBatchIds(ids);
|
||||
return Result.success();
|
||||
}
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<?> delete(@PathVariable Long id){
|
||||
BookMapper.deleteById(id);
|
||||
return Result.success();
|
||||
}
|
||||
@GetMapping
|
||||
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String search1,
|
||||
@RequestParam(defaultValue = "") String search2,
|
||||
@RequestParam(defaultValue = "") String search3){
|
||||
LambdaQueryWrapper<Book> wrappers = Wrappers.<Book>lambdaQuery();
|
||||
if(StringUtils.isNotBlank(search1)){
|
||||
wrappers.like(Book::getIsbn,search1);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search2)){
|
||||
wrappers.like(Book::getName,search2);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search3)){
|
||||
wrappers.like(Book::getAuthor,search3);
|
||||
}
|
||||
Page<Book> BookPage =BookMapper.selectPage(new Page<>(pageNum,pageSize), wrappers);
|
||||
return Result.success(BookPage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.BookWithUser;
|
||||
import com.example.library.mapper.BookWithUserMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/bookwithuser")
|
||||
public class BookWithUserController {
|
||||
@Resource
|
||||
BookWithUserMapper BookWithUserMapper;
|
||||
//
|
||||
// @PostMapping
|
||||
// public Result<?> save(@RequestBody Book Book){
|
||||
// BookMapper.insert(Book);
|
||||
// return Result.success();
|
||||
// }
|
||||
|
||||
// // 批量删除
|
||||
// @PostMapping("/deleteBatch")
|
||||
// public Result<?> deleteBatch(@RequestBody List<Integer> ids){
|
||||
// BookMapper.deleteBatchIds(ids);
|
||||
// return Result.success();
|
||||
// }
|
||||
// @PutMapping
|
||||
// public Result<?> update(@RequestBody Book Book){
|
||||
// BookMapper.updateById(Book);
|
||||
// return Result.success();
|
||||
// }
|
||||
// @DeleteMapping("/{id}")
|
||||
// public Result<?> delete(@PathVariable Long id){
|
||||
// BookMapper.deleteById(id);
|
||||
// return Result.success();
|
||||
// }
|
||||
@PostMapping("/insertNew")
|
||||
public Result<?> insertNew(@RequestBody BookWithUser BookWithUser){
|
||||
BookWithUserMapper.insert(BookWithUser);
|
||||
return Result.success();
|
||||
}
|
||||
@PostMapping
|
||||
public Result<?> update(@RequestBody BookWithUser BookWithUser){
|
||||
UpdateWrapper<BookWithUser> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("isbn",BookWithUser.getIsbn()).eq("id",BookWithUser.getId());
|
||||
BookWithUserMapper.update(BookWithUser, updateWrapper);
|
||||
return Result.success();
|
||||
}
|
||||
//删除一条记录
|
||||
@PostMapping("/deleteRecord")
|
||||
public Result<?> deleteRecord(@RequestBody BookWithUser BookWithUser){
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("isbn",BookWithUser.getIsbn());
|
||||
map.put("id",BookWithUser.getId());
|
||||
BookWithUserMapper.deleteByMap(map);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@PostMapping("/deleteRecords")
|
||||
public Result<?> deleteRecords(@RequestBody List<BookWithUser> BookWithUsers){
|
||||
int len = BookWithUsers.size();
|
||||
for(int i=0;i<len;i++) {
|
||||
BookWithUser curRecord = BookWithUsers.get(i);
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("isbn",curRecord.getIsbn());
|
||||
map.put("id",curRecord.getId());
|
||||
BookWithUserMapper.deleteByMap(map);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
@GetMapping
|
||||
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String search1,
|
||||
@RequestParam(defaultValue = "") String search2,
|
||||
@RequestParam(defaultValue = "") String search3){
|
||||
LambdaQueryWrapper<BookWithUser> wrappers = Wrappers.<BookWithUser>lambdaQuery();
|
||||
if(StringUtils.isNotBlank(search1)){
|
||||
wrappers.like(BookWithUser::getIsbn,search1);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search2)){
|
||||
wrappers.like(BookWithUser::getBookName,search2);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search3)){
|
||||
wrappers.like(BookWithUser::getId,search3);
|
||||
}
|
||||
Page<BookWithUser> BookPage =BookWithUserMapper.selectPage(new Page<>(pageNum,pageSize), wrappers);
|
||||
return Result.success(BookPage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.library.LoginUser;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.Book;
|
||||
import com.example.library.entity.LendRecord;
|
||||
import com.example.library.entity.User;
|
||||
import com.example.library.mapper.BookMapper;
|
||||
import com.example.library.mapper.LendRecordMapper;
|
||||
import com.example.library.mapper.UserMapper;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/dashboard")
|
||||
public class DashboardController {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private LendRecordMapper lendRecordMapper;
|
||||
@Resource
|
||||
private BookMapper bookMapper;
|
||||
@GetMapping
|
||||
public Result<?> dashboardrecords(){
|
||||
int visitCount = LoginUser.getVisitCount();
|
||||
QueryWrapper<User> queryWrapper1=new QueryWrapper();
|
||||
int userCount = userMapper.selectCount(queryWrapper1);
|
||||
QueryWrapper<LendRecord> queryWrapper2=new QueryWrapper();
|
||||
int lendRecordCount = lendRecordMapper.selectCount(queryWrapper2);
|
||||
QueryWrapper<Book> queryWrapper3=new QueryWrapper();
|
||||
int bookCount = bookMapper.selectCount(queryWrapper3);
|
||||
Map<String, Object> map = new HashMap<>();//键值对形式
|
||||
map.put("visitCount", visitCount);//放置visitCount到map中
|
||||
map.put("userCount", userCount);
|
||||
map.put("lendRecordCount", lendRecordCount);
|
||||
map.put("bookCount", bookCount);
|
||||
return Result.success(map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.LendRecord;
|
||||
import com.example.library.mapper.LendRecordMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/LendRecord")
|
||||
public class LendRecordController {
|
||||
@Resource
|
||||
LendRecordMapper LendRecordMapper;
|
||||
|
||||
@DeleteMapping("/{isbn}")
|
||||
public Result<?> delete(@PathVariable String isbn){
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("isbn",isbn);
|
||||
LendRecordMapper.deleteByMap(map);
|
||||
return Result.success();
|
||||
}
|
||||
//删除一条记录
|
||||
@PostMapping("/deleteRecord")
|
||||
public Result<?> deleteRecord(@RequestBody LendRecord LendRecord){
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("isbn",LendRecord.getIsbn());
|
||||
map.put("borrownum",LendRecord.getBorrownum());
|
||||
LendRecordMapper.deleteByMap(map);
|
||||
return Result.success();
|
||||
}
|
||||
@PostMapping("/deleteRecords")
|
||||
public Result<?> deleteRecords(@RequestBody List<LendRecord> LendRecords){
|
||||
int len = LendRecords.size();
|
||||
for(int i=0;i<len;i++) {
|
||||
LendRecord curRecord = LendRecords.get(i);
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("isbn",curRecord.getIsbn());
|
||||
map.put("borrownum",curRecord.getBorrownum());
|
||||
LendRecordMapper.deleteByMap(map);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
@PostMapping
|
||||
public Result<?> save(@RequestBody LendRecord LendRecord){
|
||||
LendRecordMapper.insert(LendRecord);
|
||||
return Result.success();
|
||||
}
|
||||
@GetMapping
|
||||
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String search1,
|
||||
@RequestParam(defaultValue = "") String search2,
|
||||
@RequestParam(defaultValue = "") String search3){
|
||||
LambdaQueryWrapper<LendRecord> wrappers = Wrappers.<LendRecord>lambdaQuery();
|
||||
if(StringUtils.isNotBlank(search1)){
|
||||
wrappers.like(LendRecord::getIsbn,search1);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search2)){
|
||||
wrappers.like(LendRecord::getBookname,search2);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search3)){
|
||||
wrappers.like(LendRecord::getReaderId,search3);
|
||||
}
|
||||
Page<LendRecord> LendRecordPage =LendRecordMapper.selectPage(new Page<>(pageNum,pageSize), wrappers);
|
||||
return Result.success(LendRecordPage);
|
||||
}
|
||||
|
||||
@PutMapping("/{isbn}")
|
||||
public Result<?> update(@PathVariable String isbn,@RequestBody LendRecord lendRecord){
|
||||
UpdateWrapper<LendRecord> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("isbn",isbn);
|
||||
LendRecord lendrecord = new LendRecord();
|
||||
lendrecord.setLendTime(lendRecord.getLendTime());
|
||||
lendrecord.setReturnTime(lendRecord.getReturnTime());
|
||||
lendrecord.setStatus(lendRecord.getStatus());
|
||||
LendRecordMapper.update(lendrecord, updateWrapper);
|
||||
return Result.success();
|
||||
}
|
||||
@PutMapping("/{lendTime}")
|
||||
public Result<?> update2(@PathVariable Date lendTime, @RequestBody LendRecord lendRecord){
|
||||
UpdateWrapper<LendRecord> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("lendTime",lendTime);
|
||||
LendRecord lendrecord = new LendRecord();
|
||||
lendrecord.setReturnTime(lendRecord.getReturnTime());
|
||||
lendrecord.setStatus(lendRecord.getStatus());
|
||||
LendRecordMapper.update(lendrecord, updateWrapper);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.LendRecord;
|
||||
import com.example.library.mapper.LendRecordMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/LendRecord1")
|
||||
public class LendRecordController1 {
|
||||
@Resource
|
||||
LendRecordMapper LendRecordMapper;
|
||||
@PutMapping
|
||||
public Result<?> update2( @RequestBody LendRecord lendRecord){
|
||||
UpdateWrapper<LendRecord> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("isbn",lendRecord.getIsbn()).eq("reader_id",lendRecord.getReaderId()).eq("borrownum",lendRecord.getBorrownum());
|
||||
LendRecord lendrecord = new LendRecord();
|
||||
lendrecord.setReturnTime(lendRecord.getReturnTime());
|
||||
lendrecord.setStatus(lendRecord.getStatus());
|
||||
LendRecordMapper.update(lendrecord, updateWrapper);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.library.LoginUser;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.User;
|
||||
import com.example.library.mapper.UserMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.example.library.utils.TokenUtils;
|
||||
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
@Resource
|
||||
UserMapper userMapper;
|
||||
@PostMapping("/register")
|
||||
public Result<?> register(@RequestBody User user){
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
|
||||
if(res != null)
|
||||
{
|
||||
return Result.error("-1","用户名已重复");
|
||||
}
|
||||
userMapper.insert(user);
|
||||
return Result.success();
|
||||
}
|
||||
@CrossOrigin
|
||||
@PostMapping("/checkusername")
|
||||
public Result<?> checkusername(@RequestBody User user){
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","用户名不存在");
|
||||
}
|
||||
return Result.success("0");
|
||||
}
|
||||
@CrossOrigin
|
||||
@PostMapping("/sendsms")
|
||||
public Result<?> sendsms(@RequestBody User user, HttpServletRequest request){
|
||||
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getPhone,user.getPhone()).eq(User::getUsername,user.getUsername()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","手机号错误");
|
||||
}
|
||||
HttpSession session = request.getSession();
|
||||
session.setAttribute("code",1234);
|
||||
System.out.println(session.getAttribute("code"));
|
||||
return Result.success("0");
|
||||
}
|
||||
@CrossOrigin
|
||||
@GetMapping("/checksms")
|
||||
public Result<?> checksms(HttpServletRequest request){
|
||||
HttpSession session = request.getSession();
|
||||
String code = (String)session.getAttribute("code");
|
||||
System.out.println(code);
|
||||
|
||||
try {
|
||||
if ("1234".equals(request.getParameter("code"))) {
|
||||
return Result.success("0");
|
||||
} else {
|
||||
return Result.error("-1", "验证码错误");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return Result.error("-1", "验证码错误");
|
||||
}
|
||||
|
||||
}
|
||||
@CrossOrigin
|
||||
@PostMapping("/resetpassword")
|
||||
public Result<?> resetpassword(@RequestBody User user){
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
|
||||
//User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPhone,user.getPhone()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","用户名或手机号错误");
|
||||
}
|
||||
res.setPassword(user.getPassword());
|
||||
userMapper.updateById(res);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@CrossOrigin
|
||||
@PostMapping("/login")
|
||||
public Result<?> login(@RequestBody User user){
|
||||
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPassword,user.getPassword()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","用户名或密码错误");
|
||||
}
|
||||
String token = TokenUtils.genToken(res);
|
||||
res.setToken(token);
|
||||
LoginUser loginuser = new LoginUser();
|
||||
loginuser.addVisitCount();
|
||||
return Result.success(res);
|
||||
}
|
||||
@PostMapping("/info")
|
||||
public Result<?> userinfo(@RequestBody User user){
|
||||
System.out.println(user);
|
||||
User user1 = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getId,user.getId()));
|
||||
System.out.println(user1);
|
||||
return Result.success(user1);
|
||||
}
|
||||
@PostMapping
|
||||
public Result<?> save(@RequestBody User user){
|
||||
if(user.getPassword() == null){
|
||||
user.setPassword("abc123456");
|
||||
}
|
||||
userMapper.insert(user);
|
||||
return Result.success();
|
||||
}
|
||||
@PutMapping("/password")
|
||||
public Result<?> update( @RequestParam Integer id,
|
||||
@RequestParam String password2){
|
||||
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id",id);
|
||||
User user = new User();
|
||||
user.setPassword(password2);
|
||||
userMapper.update(user,updateWrapper);
|
||||
return Result.success();
|
||||
}
|
||||
@PutMapping
|
||||
public Result<?> password(@RequestBody User user){
|
||||
userMapper.updateById(user);
|
||||
return Result.success();
|
||||
}
|
||||
@PostMapping("/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestBody List<Integer> ids){
|
||||
userMapper.deleteBatchIds(ids);
|
||||
return Result.success();
|
||||
}
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<?> delete(@PathVariable Long id){
|
||||
userMapper.deleteById(id);
|
||||
return Result.success();
|
||||
}
|
||||
@GetMapping
|
||||
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String search){
|
||||
LambdaQueryWrapper<User> wrappers = Wrappers.<User>lambdaQuery();
|
||||
if(StringUtils.isNotBlank(search)){
|
||||
wrappers.like(User::getNickName,search);
|
||||
}
|
||||
wrappers.like(User::getRole,2);
|
||||
Page<User> userPage =userMapper.selectPage(new Page<>(pageNum,pageSize), wrappers);
|
||||
return Result.success(userPage);
|
||||
}
|
||||
@GetMapping("/usersearch")
|
||||
public Result<?> findPage2(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String search1,
|
||||
@RequestParam(defaultValue = "") String search2,
|
||||
@RequestParam(defaultValue = "") String search3,
|
||||
@RequestParam(defaultValue = "") String search4){
|
||||
LambdaQueryWrapper<User> wrappers = Wrappers.<User>lambdaQuery();
|
||||
if(StringUtils.isNotBlank(search1)){
|
||||
wrappers.like(User::getId,search1);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search2)){
|
||||
wrappers.like(User::getNickName,search2);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search3)){
|
||||
wrappers.like(User::getPhone,search3);
|
||||
}
|
||||
if(StringUtils.isNotBlank(search4)){
|
||||
wrappers.like(User::getAddress,search4);
|
||||
}
|
||||
wrappers.like(User::getRole,2);
|
||||
Page<User> userPage =userMapper.selectPage(new Page<>(pageNum,pageSize), wrappers);
|
||||
return Result.success(userPage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.example.library.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.User;
|
||||
import com.example.library.mapper.UserMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/forget")
|
||||
public class forgetController {
|
||||
@Resource
|
||||
UserMapper userMapper;
|
||||
@CrossOrigin
|
||||
@PostMapping("/checkusername")
|
||||
public Result<?> checkusername(@RequestBody User user){
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","用户名不存在");
|
||||
}
|
||||
return Result.success("0");
|
||||
}
|
||||
@CrossOrigin
|
||||
@PostMapping("/sendsms")
|
||||
public Result<?> sendsms(@RequestBody User user, HttpServletRequest request){
|
||||
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getPhone,user.getPhone()).eq(User::getUsername,user.getUsername()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","手机号错误");
|
||||
}
|
||||
HttpSession session = request.getSession();
|
||||
session.setAttribute("code",1234);
|
||||
System.out.println(session.getAttribute("code"));
|
||||
return Result.success("0");
|
||||
}
|
||||
@CrossOrigin
|
||||
@GetMapping("/checksms")
|
||||
public Result<?> checksms(HttpServletRequest request){
|
||||
HttpSession session = request.getSession();
|
||||
String code = (String)session.getAttribute("code");
|
||||
System.out.println(code);
|
||||
|
||||
try {
|
||||
if ("1234".equals(request.getParameter("code"))) {
|
||||
return Result.success("0");
|
||||
} else {
|
||||
return Result.error("-1", "验证码错误");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return Result.error("-1", "验证码错误");
|
||||
}
|
||||
|
||||
}
|
||||
@CrossOrigin
|
||||
@PostMapping("/resetpassword")
|
||||
public Result<?> resetpassword(@RequestBody User user){
|
||||
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
|
||||
//User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPhone,user.getPhone()));
|
||||
if(res == null)
|
||||
{
|
||||
return Result.error("-1","用户名或手机号错误");
|
||||
}
|
||||
res.setPassword(user.getPassword());
|
||||
userMapper.updateById(res);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
33
library/src/main/java/com/example/library/entity/Book.java
Normal file
33
library/src/main/java/com/example/library/entity/Book.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.example.library.entity;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("book")
|
||||
@Data
|
||||
|
||||
public class Book {
|
||||
|
||||
@TableId (type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private String isbn;
|
||||
private String name;
|
||||
private BigDecimal price;
|
||||
private String author;
|
||||
private Integer borrownum;
|
||||
private String publisher;
|
||||
@JsonFormat(locale="zh",timezone="GMT+8", pattern="yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
private String status;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.example.library.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("bookwithuser")
|
||||
@Data
|
||||
public class BookWithUser {
|
||||
private Integer id;
|
||||
private String isbn;
|
||||
private String bookName;
|
||||
private String nickName;
|
||||
@JsonFormat(locale="zh",timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date lendtime;
|
||||
@JsonFormat(locale="zh",timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date deadtime;
|
||||
private Integer prolong;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.example.library.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("lend_record")
|
||||
@Data
|
||||
public class LendRecord {
|
||||
private Integer readerId;
|
||||
private String isbn;
|
||||
private String bookname;
|
||||
@JsonFormat(locale="zh",timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date lendTime;
|
||||
@JsonFormat(locale="zh",timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date returnTime;
|
||||
private String status;
|
||||
private Integer borrownum;
|
||||
|
||||
}
|
||||
24
library/src/main/java/com/example/library/entity/User.java
Normal file
24
library/src/main/java/com/example/library/entity/User.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.example.library.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@TableName("user")
|
||||
@Data
|
||||
public class User {
|
||||
@TableId (type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private String username;
|
||||
private String nickName;
|
||||
private String password;
|
||||
private String sex;
|
||||
private String address;
|
||||
private String phone;
|
||||
@TableField(exist = false) //表中没有token不会报错仍能编译运行
|
||||
private String token;
|
||||
private Integer role;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.example.library.filter;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.example.library.commom.Result;
|
||||
import com.example.library.entity.User;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class AccessControlInterceptor implements HandlerInterceptor {
|
||||
@Autowired
|
||||
private User user;
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
// 获取请求中的所有 Cookie
|
||||
try {
|
||||
String token = request.getHeader("token");
|
||||
String aud = JWT.decode(token).getAudience().get(0);
|
||||
Integer userId = Integer.valueOf(aud);
|
||||
|
||||
if (userId != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
}
|
||||
response.setContentType("application/json");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
// 将 ErrorResult 对象转换为 JSON 格式
|
||||
String jsonResponse = mapper.writeValueAsString(Result.noAuth());
|
||||
response.getWriter().println(jsonResponse);
|
||||
// 用户信息验证失败,返回 false,并返回错误响应或者重定向到登录页面等操作
|
||||
return false;
|
||||
}
|
||||
|
||||
// 用户信息验证的方法,可以根据具体业务逻辑来实现
|
||||
private boolean validateToken(String token) {
|
||||
return user.getToken().equals(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.library.filter;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("*") // 允许访问的域名,可以指定多个或使用通配符 *
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP方法
|
||||
.allowCredentials(true); // 允许传输凭证信息
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.example.library.filter;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class CorsFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
|
||||
response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
response.setHeader("allowCredentials","true");
|
||||
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
} else {
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.example.library.filter;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new AccessControlInterceptor())// 添加要拦截的路径
|
||||
.excludePathPatterns("/user/login").excludePathPatterns("/forget/**").excludePathPatterns("/user/register"); // 排除不需要拦截的路径
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.example.library.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.library.entity.Book;
|
||||
|
||||
|
||||
public interface BookMapper extends BaseMapper<Book> {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.example.library.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.library.entity.BookWithUser;
|
||||
|
||||
public interface BookWithUserMapper extends BaseMapper<BookWithUser> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.example.library.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.library.entity.LendRecord;
|
||||
|
||||
|
||||
public interface LendRecordMapper extends BaseMapper<LendRecord> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.example.library.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.library.entity.User;
|
||||
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
// @Insert("INSERT INTO user_table (username, password, email) VALUES (#{username}, #{password}, #{email})")
|
||||
// void insertUser(User user);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.library.utils;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
|
||||
import com.example.library.entity.User;
|
||||
import com.example.library.mapper.UserMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TokenUtils {
|
||||
|
||||
@Autowired
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
private static UserMapper staticUserMapper;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
staticUserMapper = userMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
public static String genToken(User user) {
|
||||
return JWT.create().withExpiresAt(DateUtil.offsetDay(new Date(), 1)).withAudience(user.getId().toString())
|
||||
.sign(Algorithm.HMAC256(user.getPassword()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token中的用户信息
|
||||
* @return
|
||||
*/
|
||||
public static User getUser() {
|
||||
try {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String token = request.getHeader("token");
|
||||
String aud = JWT.decode(token).getAudience().get(0);
|
||||
Integer userId = Integer.valueOf(aud);
|
||||
return staticUserMapper.selectById(userId);
|
||||
} catch (Exception e) {
|
||||
log.error("解析token失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
library/src/main/resources/application.yaml
Normal file
19
library/src/main/resources/application.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
server:
|
||||
port: 9090
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/springboot-vue?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
|
||||
username: root
|
||||
password: 123456
|
||||
|
||||
|
||||
application:
|
||||
name: libirary-service
|
||||
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 192.168.202.220:8848
|
||||
|
||||
1
library/src/main/resources/static/css/app.90e92dc6.css
Normal file
1
library/src/main/resources/static/css/app.90e92dc6.css
Normal file
@@ -0,0 +1 @@
|
||||
.icon[data-v-f4e55176]{width:40px;height:40px;padding-top:5px;padding-right:10px}.icon[data-v-f5394220]{width:30px;height:30px;padding-top:5px;padding-right:10px}*{margin:0;padding:0;box-sizing:border-box}.icon{width:1em;height:1em;vertical-align:-.15em;fill:currentColor;overflow:hidden}
|
||||
@@ -0,0 +1 @@
|
||||
.box-card[data-v-4dae75ff]{width:80%;margin-bottom:25px;margin-left:10px}.clearfix[data-v-4dae75ff]{text-align:center;font-size:15px}.text[data-v-4dae75ff]{text-align:center;font-size:24px;font-weight:700;vertical-align:super}#main[data-v-4dae75ff]{width:100%;height:450px;margin-top:20px}.icon[data-v-4dae75ff]{width:50px;height:50px;padding-top:5px;padding-right:10px}
|
||||
@@ -0,0 +1 @@
|
||||
.ValidCode[data-v-4bf328f2]{display:flex;justify-content:center;align-items:center;cursor:pointer}.ValidCode span[data-v-4bf328f2]{display:inline-block}.login-container[data-v-70b225b5]{position:fixed;width:100%;height:100%;background:url(../img/bg2.dd39329b.svg);background-size:contain}.login-page[data-v-70b225b5]{border-radius:5px;margin:180px auto;width:350px;padding:35px 35px 15px;background:#fff;border:1px solid #eaeaea;box-shadow:0 0 25px #cac6c6}
|
||||
@@ -0,0 +1 @@
|
||||
.avatar-uploader{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader:hover{border-color:#409eff}.avatar{width:178px;height:178px;display:block}.box-card{width:60%;margin:auto;padding:20px}
|
||||
@@ -0,0 +1 @@
|
||||
.ValidCode[data-v-4bf328f2]{display:flex;justify-content:center;align-items:center;cursor:pointer}.ValidCode span[data-v-4bf328f2]{display:inline-block}.login-container[data-v-a8e2f1f2]{position:fixed;width:100%;height:100vh;background:url(../img/bg2.dd39329b.svg);background-size:contain;overflow:hidden}.login-page[data-v-a8e2f1f2]{border-radius:5px;margin:180px auto;width:350px;padding:35px 35px 15px;background:#fff;border:1px solid #eaeaea;box-shadow:0 0 25px #cac6c6}
|
||||
File diff suppressed because one or more lines are too long
BIN
library/src/main/resources/static/favicon.ico
Normal file
BIN
library/src/main/resources/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
33
library/src/main/resources/static/img/bg2.dd39329b.svg
Normal file
33
library/src/main/resources/static/img/bg2.dd39329b.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="100%" height="100%" viewBox="0 0 1400 800">
|
||||
|
||||
<rect x="1300" y="400" rx="40" ry="40" width="300" height="300" stroke="rgb(129, 201, 149)" fill="rgb(129, 201, 149)">
|
||||
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 1450 550" to="360 1450 550" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
|
||||
<path d="M 100 350 A 150 150 0 1 1 400 350 Q400 370 380 370 L 250 370 L 120 370 Q100 370 100 350" stroke="rgb(253, 214, 99)" fill="rgb(253, 214, 99)">
|
||||
<animateMotion path="M 800 -200 L 800 -300 L 800 -200" dur="20s" begin="0s" repeatCount="indefinite"/>
|
||||
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 210 530 ; -30 210 530 ; 0 210 530" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<circle cx="200" cy="150" r="20" stroke="#1a73e8" fill="#1a73e8">
|
||||
<animateMotion path="M 0 0 L 40 20 Z" dur="5s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
|
||||
<!-- 三角形 -->
|
||||
<path d="M 165 580 L 270 580 Q275 578 270 570 L 223 483 Q220 480 217 483 L 165 570 Q160 578 165 580" stroke="rgb(238, 103, 92)" fill="rgb(238, 103, 92)">
|
||||
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 210 530" to="360 210 530" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<circle cx="1200" cy="600" r="30" stroke="rgb(241, 243, 244)" fill="rgb(241, 243, 244)">
|
||||
<animateMotion path="M 0 0 L -20 40 Z" dur="9s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
|
||||
<path d="M 100 350 A 40 40 0 1 1 180 350 L 180 430 A 40 40 0 1 1 100 430 Z" stroke="rgb(241, 243, 244)" fill="rgb(241, 243, 244)">
|
||||
<animateMotion path="M 140 390 L 180 360 L 140 390" dur="20s" begin="0s" repeatCount="indefinite"/>
|
||||
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 140 390; -60 140 390; 0 140 390" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite"/>
|
||||
</path>
|
||||
|
||||
<rect x="400" y="600" rx="40" ry="40" width="100" height="100" stroke="rgb(129, 201, 149)" fill="rgb(129, 201, 149)">
|
||||
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="-30 550 750" to="330 550 750" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
BIN
library/src/main/resources/static/img/login.81e3ef50.png
Normal file
BIN
library/src/main/resources/static/img/login.81e3ef50.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
1
library/src/main/resources/static/index.html
Normal file
1
library/src/main/resources/static/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>vue_demo</title><link href="/css/chunk-0ef1ccea.91552112.css" rel="prefetch"><link href="/css/chunk-1d2b6d9d.750ab8fd.css" rel="prefetch"><link href="/css/chunk-1e6a6472.a9697564.css" rel="prefetch"><link href="/css/chunk-752ac4fb.e53c3c2c.css" rel="prefetch"><link href="/js/chunk-0be195b0.11a9a989.js" rel="prefetch"><link href="/js/chunk-0ef1ccea.8151085a.js" rel="prefetch"><link href="/js/chunk-1d2b6d9d.13081618.js" rel="prefetch"><link href="/js/chunk-1e6a6472.ed80c125.js" rel="prefetch"><link href="/js/chunk-25f25a31.25ed3d91.js" rel="prefetch"><link href="/js/chunk-2d0c0df2.9b822a3f.js" rel="prefetch"><link href="/js/chunk-2d0c1074.8dbc50ec.js" rel="prefetch"><link href="/js/chunk-33419c76.697ed836.js" rel="prefetch"><link href="/js/chunk-6cd47659.348c5279.js" rel="prefetch"><link href="/js/chunk-6fecba8e.e1b4f3ca.js" rel="prefetch"><link href="/js/chunk-752ac4fb.b6d0ae67.js" rel="prefetch"><link href="/css/app.90e92dc6.css" rel="preload" as="style"><link href="/css/chunk-vendors.041c0013.css" rel="preload" as="style"><link href="/js/app.3d87220e.js" rel="preload" as="script"><link href="/js/chunk-vendors.c2943193.js" rel="preload" as="script"><link href="/css/chunk-vendors.041c0013.css" rel="stylesheet"><link href="/css/app.90e92dc6.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but vue_demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.c2943193.js"></script><script src="/js/app.3d87220e.js"></script></body></html>
|
||||
2
library/src/main/resources/static/js/app.3d87220e.js
Normal file
2
library/src/main/resources/static/js/app.3d87220e.js
Normal file
File diff suppressed because one or more lines are too long
1
library/src/main/resources/static/js/app.3d87220e.js.map
Normal file
1
library/src/main/resources/static/js/app.3d87220e.js.map
Normal file
File diff suppressed because one or more lines are too long
279
library/src/main/resources/static/js/chunk-0be195b0.11a9a989.js
Normal file
279
library/src/main/resources/static/js/chunk-0be195b0.11a9a989.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-1e6a6472"],{c714:function(e,t,o){},ce40:function(e,t,o){"use strict";o.r(t);var n=o("7a23"),r=Object(n["createElementVNode"])("h2",{style:{padding:"30px"}},"个人信息",-1),c={key:0,style:{margin:"5px"}},a={key:1,style:{margin:"5px"}},l=Object(n["createTextVNode"])("男"),u=Object(n["createTextVNode"])("女"),d={style:{"text-align":"center"}},i=Object(n["createTextVNode"])("保存");function f(e,t,o,f,m,s){var b=Object(n["resolveComponent"])("el-input"),O=Object(n["resolveComponent"])("el-form-item"),j=Object(n["resolveComponent"])("el-radio"),p=Object(n["resolveComponent"])("el-form"),V=Object(n["resolveComponent"])("el-button"),h=Object(n["resolveComponent"])("el-card");return Object(n["openBlock"])(),Object(n["createElementBlock"])("div",null,[Object(n["createVNode"])(h,{style:{width:"40%","margin-left":"120px","margin-top":"40px"}},{default:Object(n["withCtx"])((function(){return[r,Object(n["createVNode"])(p,{model:m.form,ref:"form","label-width":"80px"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(O,{label:"用户名"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(b,{style:{width:"80%"},modelValue:m.form.username,"onUpdate:modelValue":t[0]||(t[0]=function(e){return m.form.username=e}),disabled:""},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(O,{label:"姓名"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(b,{style:{width:"80%"},modelValue:m.form.nickName,"onUpdate:modelValue":t[1]||(t[1]=function(e){return m.form.nickName=e})},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(O,{label:"权限"},{default:Object(n["withCtx"])((function(){return[1==m.form.role?(Object(n["openBlock"])(),Object(n["createElementBlock"])("span",c,"管理员")):Object(n["createCommentVNode"])("",!0),2==m.form.role?(Object(n["openBlock"])(),Object(n["createElementBlock"])("span",a,"读者")):Object(n["createCommentVNode"])("",!0)]})),_:1}),Object(n["createVNode"])(O,{label:"电话号码"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(b,{style:{width:"80%"},modelValue:m.form.phone,"onUpdate:modelValue":t[2]||(t[2]=function(e){return m.form.phone=e})},null,8,["modelValue"])]})),_:1}),Object(n["createVNode"])(O,{label:"性别"},{default:Object(n["withCtx"])((function(){return[Object(n["createElementVNode"])("div",null,[Object(n["createVNode"])(j,{modelValue:m.form.sex,"onUpdate:modelValue":t[3]||(t[3]=function(e){return m.form.sex=e}),label:"男"},{default:Object(n["withCtx"])((function(){return[l]})),_:1},8,["modelValue"]),Object(n["createVNode"])(j,{modelValue:m.form.sex,"onUpdate:modelValue":t[4]||(t[4]=function(e){return m.form.sex=e}),label:"女"},{default:Object(n["withCtx"])((function(){return[u]})),_:1},8,["modelValue"])])]})),_:1}),Object(n["createVNode"])(O,{label:"地址"},{default:Object(n["withCtx"])((function(){return[Object(n["createVNode"])(b,{type:"textarea",style:{width:"80%"},modelValue:m.form.address,"onUpdate:modelValue":t[5]||(t[5]=function(e){return m.form.address=e})},null,8,["modelValue"])]})),_:1})]})),_:1},8,["model"]),Object(n["createElementVNode"])("div",d,[Object(n["createVNode"])(V,{type:"primary",onClick:s.update},{default:Object(n["withCtx"])((function(){return[i]})),_:1},8,["onClick"])])]})),_:1})])}o("e9c4");var m=o("b775"),s=o("3ef4"),b={name:"Person",data:function(){return{form:{}}},created:function(){var e=sessionStorage.getItem("user")||"{}";this.form=JSON.parse(e)},methods:{update:function(){var e=this;m["a"].put("/user",this.form).then((function(t){console.log(t),"0"===t.code?(s["a"].success("更新成功"),sessionStorage.setItem("user",JSON.stringify(e.form)),e.$emit("userInfo")):s["a"].error(t.msg)}))}}},O=(o("fe6f"),o("6b0d")),j=o.n(O);const p=j()(b,[["render",f]]);t["default"]=p},e9c4:function(e,t,o){var n=o("23e7"),r=o("da84"),c=o("d066"),a=o("2ba4"),l=o("e330"),u=o("d039"),d=r.Array,i=c("JSON","stringify"),f=l(/./.exec),m=l("".charAt),s=l("".charCodeAt),b=l("".replace),O=l(1..toString),j=/[\uD800-\uDFFF]/g,p=/^[\uD800-\uDBFF]$/,V=/^[\uDC00-\uDFFF]$/,h=function(e,t,o){var n=m(o,t-1),r=m(o,t+1);return f(p,e)&&!f(V,r)||f(V,e)&&!f(p,n)?"\\u"+O(s(e,0),16):e},N=u((function(){return'"\\udf06\\ud834"'!==i("\udf06\ud834")||'"\\udead"'!==i("\udead")}));i&&n({target:"JSON",stat:!0,forced:N},{stringify:function(e,t,o){for(var n=0,r=arguments.length,c=d(r);n<r;n++)c[n]=arguments[n];var l=a(i,null,c);return"string"==typeof l?b(l,j,h):l}})},fe6f:function(e,t,o){"use strict";o("c714")}}]);
|
||||
//# sourceMappingURL=chunk-1e6a6472.ed80c125.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0c1074"],{"43fe":function(e,t,r){"use strict";r.r(t);var o=r("7a23"),n=Object(o["createTextVNode"])("提交"),a=Object(o["createTextVNode"])("重置");function s(e,t,r,s,c,u){var l=Object(o["resolveComponent"])("el-input"),d=Object(o["resolveComponent"])("el-form-item"),i=Object(o["resolveComponent"])("el-button"),f=Object(o["resolveComponent"])("el-form"),p=Object(o["resolveComponent"])("el-card");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",null,[Object(o["createVNode"])(p,{style:{width:"40%","margin-left":"120px","margin-top":"40px"}},{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(f,{ref:"form",model:c.form,"status-icon":"",rules:c.rules,"label-width":"100px",class:"demo-ruleForm"},{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(d,{label:"老密码",prop:"password2"},{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(l,{modelValue:c.form.password2,"onUpdate:modelValue":t[0]||(t[0]=function(e){return c.form.password2=e}),type:"password",autocomplete:"off"},null,8,["modelValue"])]})),_:1}),Object(o["createVNode"])(d,{label:"新密码",prop:"password"},{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(l,{modelValue:c.form2.password,"onUpdate:modelValue":t[1]||(t[1]=function(e){return c.form2.password=e}),type:"password",autocomplete:"off"},null,8,["modelValue"])]})),_:1}),Object(o["createVNode"])(d,{label:"确认新密码",prop:"checkpassword"},{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(l,{modelValue:c.form.checkpassword,"onUpdate:modelValue":t[2]||(t[2]=function(e){return c.form.checkpassword=e}),type:"password",autocomplete:"off"},null,8,["modelValue"])]})),_:1}),Object(o["createVNode"])(d,null,{default:Object(o["withCtx"])((function(){return[Object(o["createVNode"])(i,{type:"primary",onClick:u.submitForm,style:{"text-align":"center"}},{default:Object(o["withCtx"])((function(){return[n]})),_:1},8,["onClick"]),Object(o["createVNode"])(i,{onClick:t[3]||(t[3]=function(e){return u.resetForm("form")}),style:{"text-align":"center"}},{default:Object(o["withCtx"])((function(){return[a]})),_:1})]})),_:1})]})),_:1},8,["model","rules"])]})),_:1})])}var c=r("b775"),u=r("3ef4"),l={name:"Password",data:function(){var e=this,t=function(t,r,o){""==r?o(new Error("请输入老密码")):(e.form.password2!==e.form.truepassword&&o(new Error("密码错误")),o())},r=function(e,t,r){""===t?r(new Error("请输入新密码")):r()},o=function(t,r,o){""===r?o(new Error("请再次输入密码")):r!==e.form2.password?o(new Error("两次输入密码不匹配")):o()};return{form:{password2:"",checkpassword:"",truepassword:""},form2:{password:"",id:0},rules:{password:[{validator:r,trigger:"blur",required:!0}],checkpassword:[{validator:o,trigger:"blur",required:!0}],password2:[{validator:t,trigger:"blur",required:!0}]}}},created:function(){var e=JSON.parse(sessionStorage.getItem("user"));this.form.truepassword=e.password,this.form2.id=e.id},methods:{submitForm:function(){var e=this;this.$refs["form"].validate((function(t){t&&c["a"].put("/user",e.form2).then((function(t){0==t.code?(u["a"].success("密码修改成功,请重新登录"),sessionStorage.removeItem("user"),e.$router.push("/login")):u["a"].error(t.msg)}))}))},resetForm:function(e){this.$refs[e].resetFields()}}},d=r("6b0d"),i=r.n(d);const f=i()(l,[["render",s]]);t["default"]=f}}]);
|
||||
//# sourceMappingURL=chunk-2d0c1074.8dbc50ec.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
117
pom.xml
Normal file
117
pom.xml
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>org.example</groupId>
|
||||
<artifactId>security-api-demo</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<modules>
|
||||
<module>gateway</module>
|
||||
<module>common</module>
|
||||
<module>user</module>
|
||||
<module>library</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!--spring boot-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<!--spring cloud-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>Hoxton.SR6</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||
<version>2.2.1.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<!--lombok-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.10</version>
|
||||
</dependency>
|
||||
<!--commons-langs-->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.11</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<!--json-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.73</version>
|
||||
</dependency>
|
||||
<!-- JWT -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.15</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
<!-- java8 环境-->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
46
user/pom.xml
Normal file
46
user/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>security-api-demo</artifactId>
|
||||
<groupId>org.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>user</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<!--spring cloud alibaba-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!--日志-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
<!--依赖common-->
|
||||
<dependency>
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
25
user/src/main/java/com/demo/user/UserApplication.java
Normal file
25
user/src/main/java/com/demo/user/UserApplication.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.demo.user;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/24 23:59
|
||||
* //
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
public class UserApplication {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(UserApplication.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.demo.user.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.demo.user.form.UserForm;
|
||||
import com.demo.user.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/25 22:11
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("/login")
|
||||
public UserForm login(@RequestBody UserForm userForm) {
|
||||
|
||||
return userForm;
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
public JSONObject detail(@RequestParam("id") Long id) {
|
||||
|
||||
return userService.detail(id);
|
||||
}
|
||||
}
|
||||
21
user/src/main/java/com/demo/user/form/UserForm.java
Normal file
21
user/src/main/java/com/demo/user/form/UserForm.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.demo.user.form;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/25 23:55
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserForm {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
}
|
||||
51
user/src/main/java/com/demo/user/service/UserService.java
Normal file
51
user/src/main/java/com/demo/user/service/UserService.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.demo.user.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.demo.user.form.UserForm;
|
||||
import com.demo.utils.TokenUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/25 22:21
|
||||
*/
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
|
||||
private static final String USERNAME = "admin";
|
||||
|
||||
private static final String PASSWORD = "123456";
|
||||
|
||||
private static final Long USER_ID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 模拟 登录 username = admin, password =123456,user_id 1L 登录成功 返回token
|
||||
*/
|
||||
public String login(UserForm userForm) {
|
||||
|
||||
String username = userForm.getUsername();
|
||||
String password = userForm.getPassword();
|
||||
|
||||
if (USERNAME.equals(username) && PASSWORD.equals(password)) {
|
||||
JSONObject userInfo = new JSONObject();
|
||||
userInfo.put("username", USERNAME);
|
||||
userInfo.put("password", PASSWORD);
|
||||
userInfo.put("userId", USER_ID);
|
||||
return TokenUtils.createToken(userInfo.toJSONString());
|
||||
}
|
||||
|
||||
return "账号密码不正确";
|
||||
}
|
||||
|
||||
|
||||
public JSONObject detail(Long id) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("id", id);
|
||||
jsonObject.put("name", "admin");
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
13
user/src/main/resources/application.yml
Normal file
13
user/src/main/resources/application.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
server:
|
||||
port: 8000
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: user-service
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 192.168.202.219:8849
|
||||
redis:
|
||||
port: 6379
|
||||
host: 127.0.0.1
|
||||
59
user/src/test/java/com/rosh/RsaTest.java
Normal file
59
user/src/test/java/com/rosh/RsaTest.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.rosh;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.demo.utils.RSAUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: rosh
|
||||
* @Date: 2021/10/25 22:30
|
||||
*/
|
||||
public class RsaTest {
|
||||
|
||||
/**
|
||||
* 用测试生成的公钥,私钥赋值
|
||||
*/
|
||||
private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFtTlL61IqIGd+fRLUhJ0MjsqFXFJswCohJ45m51WvbxDPRP3gllW0WChk74D5JEOpMDSWo4C7RfoGlBRNW7kQ6qYGukYZ5jgYpzoT0+gp3on96fQXEyQJysv9xiTPIdmSXXVVj1HAOJw29RbzxIVKUSzzPXvEtXRTtCC1+wkAJQIDAQAB";
|
||||
|
||||
private static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIW1OUvrUiogZ359EtSEnQyOyoVcUmzAKiEnjmbnVa9vEM9E/eCWVbRYKGTvgPkkQ6kwNJajgLtF+gaUFE1buRDqpga6RhnmOBinOhPT6Cneif3p9BcTJAnKy/3GJM8h2ZJddVWPUcA4nDb1FvPEhUpRLPM9e8S1dFO0ILX7CQAlAgMBAAECgYBC4amtbiKFa/wY61tV7pfYRjzLhKi+OUlZmD3E/4Z+4KGZ7DrJ8qkgMtDR3HO5LAikQrare1HTW2d7juqw32ascu+uDObf4yrYNKin+ZDLUYvIDfLhThPxnZJwQ/trdtfxO3VM//XbwZacmwYbAsYW/3QPUXwwOPAgbC2oth8kqQJBANKLyXcdjZx4cwJVl7xNeC847su8y6bPpcBASsaQloCIPiNBIg1h76dpfEGIQBYWJWbBsxtHe/MhOmz7fNFDS2sCQQCiktYZR0dZNH4eNX329LoRuBiltpr9tf36rVOlKr1GSHkLYEHF2qtyXV2mdrY8ZWpvuo3qm1oSLaqmop2rN9avAkBHk85B+IIUF77BpGeZVJzvMOO9z8lMRHuNCE5jgvQnbinxwkrZUdovh+T+QlvHJnBApslFFOBGn51FP5oHamFRAkEAmwZmPsinkrrpoKjlqz6GyCrC5hKRDWoj/IyXfKKaxpCJTH3HeoIghvfdO8Vr1X/n1Q8SESt+4mLFngznSMQAZQJBAJx07bCFYbA2IocfFV5LTEYTIiUeKdue2NP2yWqZ/+tB5H7jNwQTJmX1mn0W/sZm4+nJM7SjfETpNZhH49+rV6U=";
|
||||
|
||||
|
||||
/**
|
||||
* 生成公钥私钥
|
||||
*/
|
||||
@Test
|
||||
public void generateRsaKey() {
|
||||
Map<String, String> map = RSAUtils.generateRasKey();
|
||||
System.out.println("随机生成的公钥为:" + map.get(RSAUtils.PUBLIC_KEY));
|
||||
System.out.println("随机生成的私钥为:" + map.get(RSAUtils.PRIVATE_KEY));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密: Yeidauky/iN1/whevov2+ntzXJKAp2AHfESu5ixnDqH5iB7ww+TcfqJpDfkPHfb12Y0sVXw0gBHNJ4inkh7l2/SJBze3pKQU/mg3oyDokTia3JZIs+e80/iJcSfN+yA1JaqY+eJPYiBiOGAF2S6x0ynvJg/Wj0fwp2Tq3PDzRMo=
|
||||
*/
|
||||
@Test
|
||||
public void testEncrypt() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("username", "rosh");
|
||||
jsonObject.put("password", "123456");
|
||||
String str = jsonObject.toJSONString();
|
||||
String encrypt = RSAUtils.encrypt(str, PUBLIC_KEY);
|
||||
System.out.println(encrypt);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecrypt() {
|
||||
|
||||
String decrypt = RSAUtils.decrypt("Xt2eKETPNqCLjTjaXOx2qfotfbPRGjLsY/XqoQoQfOc/WjVJ4/QgV2CyUug4YTy0scPA0R7h91UbVDViOMoA2YFJ7DAhvrUxDBK9sw0Fn0bMkWHErSHF3c7JTz6PKYz3ZHou2+incRbY/bTu13+SzN15DgaxWV1VfOWG+DU9L6M=",
|
||||
PRIVATE_KEY);
|
||||
System.out.println(decrypt);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user