集成 jacoco

This commit is contained in:
click33
2022-08-31 14:11:14 +08:00
parent 1f398c7a17
commit 3cc3efcc6f
25 changed files with 90 additions and 103 deletions

View File

@@ -22,6 +22,17 @@
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
<!-- 冗余(生成单元测试报告) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-servlet</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
package cn.dev33.satoken.core.context.model;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.context.model.SaCookie;
/**
* SaFoxUtil 工具类测试
*
* @author kong
* @since: 2022-2-8 22:14:25
*/
public class SaCookieTest {
@Test
public void test() {
SaCookie cookie = new SaCookie("satoken", "xxxx-xxxx-xxxx-xxxx")
.setDomain("https://sa-token.dev33.cn/")
.setMaxAge(-1)
.setPath("/")
.setSameSite("Lax")
.setHttpOnly(true)
.setSecure(true);
Assertions.assertEquals(cookie.toHeaderValue(), "satoken=xxxx-xxxx-xxxx-xxxx; Domain=https://sa-token.dev33.cn/; Path=/; Secure; HttpOnly; sameSite=Lax");
}
}

View File

@@ -0,0 +1,72 @@
package cn.dev33.satoken.core.dao;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
import cn.dev33.satoken.session.SaSession;
/**
* SaTokenDao 持久层 测试
*
* @author kong
* @since: 2022-2-9 15:39:38
*/
public class SaTokenDaoTest {
SaTokenDao dao = new SaTokenDaoDefaultImpl();
@Test
public void get() {
dao.set("name", "zhangsan", 60);
Assertions.assertEquals(dao.get("name"), "zhangsan");
Assertions.assertTrue(dao.getTimeout("name") <= 60);
Assertions.assertEquals(dao.getTimeout("name2"), -2);
dao.update("name", "lisi");
Assertions.assertEquals(dao.get("name"), "lisi");
dao.updateTimeout("name", 100);
Assertions.assertTrue(dao.getTimeout("name") <= 100);
dao.delete("name");
Assertions.assertEquals(dao.get("name"), null);
}
@Test
public void getObject() {
dao.setObject("name", "zhangsan", 60);
Assertions.assertEquals(dao.getObject("name"), "zhangsan");
Assertions.assertTrue(dao.getObjectTimeout("name") <= 60);
dao.updateObject("name", "lisi");
Assertions.assertEquals(dao.getObject("name"), "lisi");
dao.updateObjectTimeout("name", 100);
Assertions.assertTrue(dao.getObjectTimeout("name") <= 100);
dao.deleteObject("name");
Assertions.assertEquals(dao.getObject("name"), null);
}
@Test
public void getSession() {
SaSession session = new SaSession("session-1001");
dao.setSession(session, 60);
Assertions.assertEquals(dao.getSession("session-1001").getId(), session.getId());
Assertions.assertTrue(dao.getSessionTimeout("session-1001") <= 60);
SaSession session2 = new SaSession("session-1001");
dao.updateSession(session2);
Assertions.assertEquals(dao.getSession("session-1001").getId(), session2.getId());
dao.updateSessionTimeout("session-1001", 100);
Assertions.assertTrue(dao.getSessionTimeout("session-1001") <= 100);
dao.deleteSession("session-1001");
Assertions.assertEquals(dao.getSession("session-1001"), null);
}
}

View File

@@ -0,0 +1,34 @@
package cn.dev33.satoken.core.fun;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.fun.IsRunFunction;
/**
* IsRunFunction 测试
*
* @author kong
* @since: 2022-2-9 16:11:10
*/
public class IsRunFunctionTest {
@Test
public void test() {
class TempClass{
int count = 1;
}
TempClass obj = new TempClass();
IsRunFunction fun = new IsRunFunction(true);
fun.exe(()->{
obj.count = 2;
}).noExe(()->{
obj.count = 3;
});
Assertions.assertEquals(obj.count, 2);
}
}

View File

@@ -0,0 +1,4 @@
/**
* 核心包测试
*/
package cn.dev33.satoken.core;

View File

@@ -0,0 +1,24 @@
package cn.dev33.satoken.core.secure;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.secure.BCrypt;
/**
* BCrypt 加密测试
*
* @author dream.
* @since 2022/1/20
*/
public class BCryptTest {
@Test
public void checkpwTest() {
final String hashed = BCrypt.hashpw("12345");
// System.out.println(hashed);
Assertions.assertTrue(BCrypt.checkpw("12345", hashed));
Assertions.assertFalse(BCrypt.checkpw("123456", hashed));
}
}

View File

@@ -0,0 +1,30 @@
package cn.dev33.satoken.core.secure;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.secure.SaBase64Util;
/**
* SaBase64Util 测试
*
* @author kong
* @since: 2022-2-9
*/
public class SaBase64UtilTest {
@Test
public void test() {
// 文本
String text = "Sa-Token 一个轻量级java权限认证框架";
// 使用Base64编码
String base64Text = SaBase64Util.encode(text);
Assertions.assertEquals(base64Text, "U2EtVG9rZW4g5LiA5Liq6L276YeP57qnamF2Yeadg+mZkOiupOivgeahhuaetg==");
// 使用Base64解码
String text2 = SaBase64Util.decode(base64Text);
Assertions.assertEquals(text2, "Sa-Token 一个轻量级java权限认证框架");
}
}

View File

@@ -0,0 +1,66 @@
package cn.dev33.satoken.core.secure;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.secure.SaSecureUtil;
/**
* SaSecureUtil 加密工具类 测试
*
* @author kong
* @since: 2022-2-9
*/
public class SaSecureUtilTest {
@Test
public void test() {
// md5加密
Assertions.assertEquals(SaSecureUtil.md5("123456"), "e10adc3949ba59abbe56e057f20f883e");
// sha1加密
Assertions.assertEquals(SaSecureUtil.sha1("123456"), "7c4a8d09ca3762af61e59520943dc26494f8941b");
// sha256加密
Assertions.assertEquals(SaSecureUtil.sha256("123456"), "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92");
// md5加盐加密: md5(md5(str) + md5(salt))
Assertions.assertEquals(SaSecureUtil.md5BySalt("123456", "salt"), "f52020dca765fd3943ed40a615dc2c5c");
}
@Test
public void aesEncrypt() {
// 定义秘钥和明文
String key = "123456";
String text = "Sa-Token 一个轻量级java权限认证框架";
// 加密
String ciphertext = SaSecureUtil.aesEncrypt(key, text);
Assertions.assertEquals(ciphertext, "KmSqfwxY5BRuWoHMWJqtebcOZ2lEEZaj2OSi1Ei8pRx4zdi24wsnwsTQVjbXRQ0M");
// 解密
String text2 = SaSecureUtil.aesDecrypt(key, ciphertext);
Assertions.assertEquals(text2, "Sa-Token 一个轻量级java权限认证框架");
}
@Test
public void rsaEncryptByPublic() {
// 定义私钥和公钥
String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAO+wmt01pwm9lHMdq7A8gkEigk0XKMfjv+4IjAFhWCSiTeP7dtlnceFJbkWxvbc7Qo3fCOpwmfcskwUc3VSgyiJkNJDs9ivPbvlt8IU2bZ+PBDxYxSCJFrgouVOpAr8ar/b6gNuYTi1vt3FkGtSjACFb002/68RKUTye8/tdcVilAgMBAAECgYA1COmrSqTUJeuD8Su9ChZ0HROhxR8T45PjMmbwIz7ilDsR1+E7R4VOKPZKW4Kz2VvnklMhtJqMs4MwXWunvxAaUFzQTTg2Fu/WU8Y9ha14OaWZABfChMZlpkmpJW9arKmI22ZuxCEsFGxghTiJQ3tK8npj5IZq5vk+6mFHQ6aJAQJBAPghz91Dpuj+0bOUfOUmzi22obWCBncAD/0CqCLnJlpfOoa9bOcXSusGuSPuKy5KiGyblHMgKI6bq7gcM2DWrGUCQQD3SkOcmia2s/6i7DUEzMKaB0bkkX4Ela/xrfV+A3GzTPv9bIBamu0VIHznuiZbeNeyw7sVo4/GTItq/zn2QJdBAkEA8xHsVoyXTVeShaDIWJKTFyT5dJ1TR++/udKIcuiNIap34tZdgGPI+EM1yoTduBM7YWlnGwA9urW0mj7F9e9WIQJAFjxqSfmeg40512KP/ed/lCQVXtYqU7U2BfBTg8pBfhLtEcOg4wTNTroGITwe2NjL5HovJ2n2sqkNXEio6Ji0QQJAFLW1Kt80qypMqot+mHhS+0KfdOpaKeMWMSR4Ij5VfE63WzETEeWAMQESxzhavN1WOTb3/p6icgcVbgPQBaWhGg==";
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvsJrdNacJvZRzHauwPIJBIoJNFyjH47/uCIwBYVgkok3j+3bZZ3HhSW5Fsb23O0KN3wjqcJn3LJMFHN1UoMoiZDSQ7PYrz275bfCFNm2fjwQ8WMUgiRa4KLlTqQK/Gq/2+oDbmE4tb7dxZBrUowAhW9NNv+vESlE8nvP7XXFYpQIDAQAB";
// 文本
String text = "Sa-Token 一个轻量级java权限认证框架";
// 使用公钥加密
String ciphertext = SaSecureUtil.rsaEncryptByPublic(publicKey, text);
// Assert.assertEquals(ciphertext, "d9e01fd105b059e975c524a1f4dccbe10dfc3a23b931a9e168ecb0a5758a29c45532254679f86cf83a63e5cc21ef631802fe70ea47e7519f5d96e0d1fab38a6f6dbebdb34b106ce7f27c341838e4e88a8ff3298c519c29a3f0944cf8f668bfecd9394f16945d85d84c4d813d12ecadf34bfb21850c383977b5b2de848fa40995");
// 使用私钥解密
String text2 = SaSecureUtil.rsaDecryptByPrivate(privateKey, ciphertext);
Assertions.assertEquals(text2, "Sa-Token 一个轻量级java权限认证框架");
}
}

View File

@@ -0,0 +1,58 @@
package cn.dev33.satoken.core.session;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.session.SaSession;
/**
* SaSession 测试
*
* @author kong
* @since: 2022-2-9
*/
public class SaSessionTest {
@Test
public void test() {
SaSession session = new SaSession("session-1001");
Assertions.assertEquals(session.getId(), "session-1001");
// 基础取值
session.set("name", "zhangsan");
session.set("age", 18);
Assertions.assertEquals(session.get("name"), "zhangsan");
Assertions.assertEquals((int)session.get("age", 20), 18);
Assertions.assertEquals((int)session.get("age2", 20), 20);
Assertions.assertEquals(session.getModel("age", Double.class).getClass(), Double.class);
// 复杂取值
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
}
User user = new User("zhangsan", 18);
session.set("user", user);
User user2 = session.getModel("user", User.class);
Assertions.assertNotNull(user2);
Assertions.assertEquals(user2.name, "zhangsan");
Assertions.assertEquals(user2.age, 18);
// Token签名
session.addTokenSign("xxxx-xxxx-xxxx-xxxx-1", "PC");
session.addTokenSign("xxxx-xxxx-xxxx-xxxx-2", "APP");
Assertions.assertEquals(session.getTokenSignList().size(), 2);
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-1").getDevice(), "PC");
Assertions.assertEquals(session.getTokenSign("xxxx-xxxx-xxxx-xxxx-2").getDevice(), "APP");
session.removeTokenSign("xxxx-xxxx-xxxx-xxxx-1");
Assertions.assertEquals(session.getTokenSignList().size(), 1);
}
}

View File

@@ -0,0 +1,206 @@
package cn.dev33.satoken.core.util;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* SaFoxUtil 工具类测试
*
* @author kong
* @since: 2022-2-8 22:14:25
*/
public class SaFoxUtilTest {
@Test
public void getRandomString() {
String randomString = SaFoxUtil.getRandomString(8);
Assertions.assertEquals(randomString.length(), 8);
}
@Test
public void isEmpty() {
Assertions.assertFalse(SaFoxUtil.isEmpty("abc"));
Assertions.assertTrue(SaFoxUtil.isEmpty(""));
Assertions.assertTrue(SaFoxUtil.isEmpty(null));
Assertions.assertTrue(SaFoxUtil.isNotEmpty("abc"));
}
@Test
public void getMarking28() {
Assertions.assertNotEquals(SaFoxUtil.getMarking28(), SaFoxUtil.getMarking28());
}
@Test
public void formatDate() {
String formatDate = SaFoxUtil.formatDate(new Date(1644328600364L));
Assertions.assertEquals(formatDate, "2022-02-08 21:56:40");
}
@Test
public void searchList() {
// 原始数据
List<String> dataList = Arrays.asList("token1", "token2", "token3", "token4", "token5", "aaa1");
// 分页
List<String> list1 = SaFoxUtil.searchList(dataList, 1, 2, true);
Assertions.assertEquals(list1.size(), 2);
Assertions.assertEquals(list1.get(0), "token2");
Assertions.assertEquals(list1.get(1), "token3");
// 前缀筛选
List<String> list2 = SaFoxUtil.searchList(dataList, "token", "", 0, 10, true);
Assertions.assertEquals(list2.size(), 5);
// 关键字筛选
List<String> list3 = SaFoxUtil.searchList(dataList, "", "1", 0, 10, true);
Assertions.assertEquals(list3.size(), 2);
// 综合筛选
List<String> list4 = SaFoxUtil.searchList(dataList, "token", "1", 0, 10, true);
Assertions.assertEquals(list4.size(), 1);
}
@Test
public void vagueMatch() {
Assertions.assertTrue(SaFoxUtil.vagueMatch("hello*", "hello"));
Assertions.assertTrue(SaFoxUtil.vagueMatch("hello*", "hello world"));
Assertions.assertFalse(SaFoxUtil.vagueMatch("hello*", "he"));
Assertions.assertTrue(SaFoxUtil.vagueMatch("hello*", "hello*"));
Assertions.assertTrue(SaFoxUtil.vagueMatch(null, null));
Assertions.assertFalse(SaFoxUtil.vagueMatch(null, "hello"));
Assertions.assertFalse(SaFoxUtil.vagueMatch("hello*", null));
}
@Test
public void getValueByType() {
Assertions.assertEquals(SaFoxUtil.getValueByType("1", Integer.class).getClass(), Integer.class);
Assertions.assertEquals(SaFoxUtil.getValueByType("1", Long.class).getClass(), Long.class);
Assertions.assertEquals(SaFoxUtil.getValueByType("1", Double.class).getClass(), Double.class);
}
@Test
public void joinParam() {
Assertions.assertEquals(SaFoxUtil.joinParam("https://sa-token.dev33.cn", "id=1"), "https://sa-token.dev33.cn?id=1");
Assertions.assertEquals(SaFoxUtil.joinParam("https://sa-token.dev33.cn?", "id=1"), "https://sa-token.dev33.cn?id=1");
Assertions.assertEquals(SaFoxUtil.joinParam("https://sa-token.dev33.cn?name=zhang", "id=1"), "https://sa-token.dev33.cn?name=zhang&id=1");
Assertions.assertEquals(SaFoxUtil.joinParam("https://sa-token.dev33.cn?name=zhang&", "id=1"), "https://sa-token.dev33.cn?name=zhang&id=1");
Assertions.assertEquals(SaFoxUtil.joinParam("https://sa-token.dev33.cn?name=zhang&", "id", 1), "https://sa-token.dev33.cn?name=zhang&id=1");
}
@Test
public void joinSharpParam() {
Assertions.assertEquals(SaFoxUtil.joinSharpParam("https://sa-token.dev33.cn", "id=1"), "https://sa-token.dev33.cn#id=1");
Assertions.assertEquals(SaFoxUtil.joinSharpParam("https://sa-token.dev33.cn#", "id=1"), "https://sa-token.dev33.cn#id=1");
Assertions.assertEquals(SaFoxUtil.joinSharpParam("https://sa-token.dev33.cn#name=zhang", "id=1"), "https://sa-token.dev33.cn#name=zhang&id=1");
Assertions.assertEquals(SaFoxUtil.joinSharpParam("https://sa-token.dev33.cn#name=zhang&", "id=1"), "https://sa-token.dev33.cn#name=zhang&id=1");
Assertions.assertEquals(SaFoxUtil.joinSharpParam("https://sa-token.dev33.cn#name=zhang&", "id", 1), "https://sa-token.dev33.cn#name=zhang&id=1");
}
@Test
public void arrayJoin() {
Assertions.assertEquals(SaFoxUtil.arrayJoin(new String[] {"a", "b", "c"}), "a,b,c");
Assertions.assertEquals(SaFoxUtil.arrayJoin(new String[] {}), "");
}
@Test
public void isUrl() {
Assertions.assertTrue(SaFoxUtil.isUrl("https://sa-token.dev33.cn"));
Assertions.assertTrue(SaFoxUtil.isUrl("https://www.baidu.com/"));
Assertions.assertFalse(SaFoxUtil.isUrl("htt://www.baidu.com/"));
Assertions.assertFalse(SaFoxUtil.isUrl("https:www.baidu.com/"));
Assertions.assertFalse(SaFoxUtil.isUrl("httpswwwbaiducom/"));
Assertions.assertFalse(SaFoxUtil.isUrl("https://www.baidu.com/,"));
}
@Test
public void encodeUrl() {
Assertions.assertEquals(SaFoxUtil.encodeUrl("https://sa-token.dev33.cn"), "https%3A%2F%2Fsa-token.dev33.cn");
Assertions.assertEquals(SaFoxUtil.decoderUrl("https%3A%2F%2Fsa-token.dev33.cn"), "https://sa-token.dev33.cn");
}
@Test
public void convertStringToList() {
List<String> list = SaFoxUtil.convertStringToList("a,b,c");
Assertions.assertEquals(list.size(), 3);
Assertions.assertEquals(list.get(0), "a");
Assertions.assertEquals(list.get(1), "b");
Assertions.assertEquals(list.get(2), "c");
List<String> list2 = SaFoxUtil.convertStringToList("a,");
Assertions.assertEquals(list2.size(), 1);
List<String> list3 = SaFoxUtil.convertStringToList(",");
Assertions.assertEquals(list3.size(), 0);
List<String> list4 = SaFoxUtil.convertStringToList("");
Assertions.assertEquals(list4.size(), 0);
List<String> list5 = SaFoxUtil.convertStringToList(null);
Assertions.assertEquals(list5.size(), 0);
}
@Test
public void convertListToString() {
List<String> list = Arrays.asList("a", "b", "c");
Assertions.assertEquals(SaFoxUtil.convertListToString(list), "a,b,c");
List<String> list2 = Arrays.asList();
Assertions.assertEquals(SaFoxUtil.convertListToString(list2), "");
}
@Test
public void convertStringToArray() {
String[] array = SaFoxUtil.convertStringToArray("a,b,c");
Assertions.assertEquals(array.length, 3);
Assertions.assertEquals(array[0], "a");
Assertions.assertEquals(array[1], "b");
Assertions.assertEquals(array[2], "c");
String[] array2 = SaFoxUtil.convertStringToArray("a,");
Assertions.assertEquals(array2.length, 1);
String[] array3 = SaFoxUtil.convertStringToArray(",");
Assertions.assertEquals(array3.length, 0);
String[] array4 = SaFoxUtil.convertStringToArray("");
Assertions.assertEquals(array4.length, 0);
String[] array5 = SaFoxUtil.convertStringToArray(null);
Assertions.assertEquals(array5.length, 0);
}
@Test
public void convertArrayToString() {
String[] array = new String[] {"a", "b", "c"};
Assertions.assertEquals(SaFoxUtil.convertArrayToString(array), "a,b,c");
String[] array2 = new String[] {};
Assertions.assertEquals(SaFoxUtil.convertArrayToString(array2), "");
}
@Test
public void emptyList() {
List<String> list = SaFoxUtil.emptyList();
Assertions.assertEquals(list.size(), 0);
}
@Test
public void toList() {
List<String> list = SaFoxUtil.toList("a","b", "c");
Assertions.assertEquals(list.size(), 3);
Assertions.assertEquals(list.get(0), "a");
Assertions.assertEquals(list.get(1), "b");
Assertions.assertEquals(list.get(2), "c");
}
}

View File

@@ -0,0 +1,35 @@
package cn.dev33.satoken.core.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import cn.dev33.satoken.util.SaResult;
/**
* SaResult 结果集 测试
*
* @author kong
* @since: 2022-2-8 22:14:25
*/
public class SaResultTest {
@Test
public void test() {
SaResult res = new SaResult(200, "ok", "zhangsan");
Assertions.assertEquals((int)res.getCode(), 200);
Assertions.assertEquals(res.getMsg(), "ok");
Assertions.assertEquals(res.getData(), "zhangsan");
res.set("age", 18);
Assertions.assertEquals(res.get("age"), 18);
Assertions.assertEquals(res.getOrDefault("age", 20), 18);
Assertions.assertEquals(res.getOrDefault("age2", 20), 20);
}
@Test
public void test2() {
Assertions.assertEquals((int)SaResult.ok().getCode(), 200);
Assertions.assertEquals((int)SaResult.error().getCode(), 500);
}
}

View File

@@ -0,0 +1,49 @@
package cn.dev33.satoken.integrate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* 登录测试
*
* @author kong
*
*/
@RestController
@RequestMapping("/acc/")
public class LoginController {
// 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
@RequestMapping("doLogin")
public SaResult doLogin(String name, String pwd) {
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
if("zhang".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
return SaResult.ok("登录成功").set("token", StpUtil.getTokenValue());
}
return SaResult.error("登录失败");
}
// 查询登录状态 ---- http://localhost:8081/acc/isLogin
@RequestMapping("isLogin")
public SaResult isLogin() {
return SaResult.data(StpUtil.isLogin());
}
// 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
@RequestMapping("tokenInfo")
public SaResult tokenInfo() {
return SaResult.data(StpUtil.getTokenInfo());
}
// 测试注销 ---- http://localhost:8081/acc/logout
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}

View File

@@ -0,0 +1,110 @@
package cn.dev33.satoken.integrate;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import cn.dev33.satoken.integrate.util.SoMap;
/**
* Sa-Token 登录API测试
*
* @author Auster
*
*/
@SpringBootTest(classes = StartUpApplication.class)
@SuppressWarnings("deprecation")
public class LoginControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mvc;
// 开始
@BeforeEach
public void before() {
mvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void testLogin() throws Exception{
// 请求
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders.post("/acc/doLogin")
.param("name", "zhang")
.param("pwd", "123456")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON_UTF8)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
// 拿到结果
SoMap so = SoMap.getSoMap().setJsonString(
mvcResult.getResponse().getContentAsString()
);
String token = so.getString("token");
// 断言
Assertions.assertTrue(mvcResult.getResponse().getHeader("Set-Cookie") != null);
Assertions.assertEquals(so.getInt("code"), 200);
Assertions.assertNotNull(token);
}
@Test
@SuppressWarnings("unchecked")
public void testLogin2() throws Exception{
// 获取token
SoMap so = request("/acc/doLogin?name=zhang&pwd=123456");
Assertions.assertNotNull(so.getString("token"));
String token = so.getString("token");
// 是否登录
SoMap so2 = request("/acc/isLogin?satoken=" + token);
Assertions.assertTrue(so2.getBoolean("data"));
// tokenInfo
SoMap so3 = request("/acc/tokenInfo?satoken=" + token);
SoMap so4 = SoMap.getSoMap((Map<String, ?>)so3.get("data"));
Assertions.assertEquals(so4.getString("tokenName"), "satoken");
Assertions.assertEquals(so4.getString("tokenValue"), token);
// 注销
request("/acc/logout?satoken=" + token);
// 是否登录
SoMap so5 = request("/acc/isLogin?satoken=" + token);
Assertions.assertFalse(so5.getBoolean("data"));
}
// 封装请求
private SoMap request(String path) throws Exception {
MvcResult mvcResult = mvc.perform(
MockMvcRequestBuilders.post(path)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON_UTF8)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
SoMap so = SoMap.getSoMap().setJsonString(
mvcResult.getResponse().getContentAsString()
);
return so;
}
}

View File

@@ -1,4 +1,4 @@
package com.pj.test;
package cn.dev33.satoken.integrate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@@ -0,0 +1,747 @@
package cn.dev33.satoken.integrate.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Map< String, Object> 是最常用的一种Map类型但是它写着麻烦
* <p>所以特封装此类继承Map进行一些扩展可以让Map更灵活使用
* <p>最新2020-12-10 新增部分构造方法
* @author kong
*/
public class SoMap extends LinkedHashMap<String, Object> {
private static final long serialVersionUID = 1L;
public SoMap() {
}
/** 以下元素会在isNull函数中被判定为Null */
public static final Object[] NULL_ELEMENT_ARRAY = {null, ""};
public static final List<Object> NULL_ELEMENT_LIST;
static {
NULL_ELEMENT_LIST = Arrays.asList(NULL_ELEMENT_ARRAY);
}
// ============================= 读值 =============================
/** 获取一个值 */
@Override
public Object get(Object key) {
if("this".equals(key)) {
return this;
}
return super.get(key);
}
/** 如果为空,则返回默认值 */
public Object get(Object key, Object defaultValue) {
Object value = get(key);
if(valueIsNull(value)) {
return defaultValue;
}
return value;
}
/** 转为String并返回 */
public String getString(String key) {
Object value = get(key);
if(value == null) {
return null;
}
return String.valueOf(value);
}
/** 如果为空,则返回默认值 */
public String getString(String key, String defaultValue) {
Object value = get(key);
if(valueIsNull(value)) {
return defaultValue;
}
return String.valueOf(value);
}
/** 转为int并返回 */
public int getInt(String key) {
Object value = get(key);
if(valueIsNull(value)) {
return 0;
}
return Integer.valueOf(String.valueOf(value));
}
/** 转为int并返回同时指定默认值 */
public int getInt(String key, int defaultValue) {
Object value = get(key);
if(valueIsNull(value)) {
return defaultValue;
}
return Integer.valueOf(String.valueOf(value));
}
/** 转为long并返回 */
public long getLong(String key) {
Object value = get(key);
if(valueIsNull(value)) {
return 0;
}
return Long.valueOf(String.valueOf(value));
}
/** 转为double并返回 */
public double getDouble(String key) {
Object value = get(key);
if(valueIsNull(value)) {
return 0.0;
}
return Double.valueOf(String.valueOf(value));
}
/** 转为boolean并返回 */
public boolean getBoolean(String key) {
Object value = get(key);
if(valueIsNull(value)) {
return false;
}
return Boolean.valueOf(String.valueOf(value));
}
/** 转为Date并返回根据自定义格式 */
public Date getDateByFormat(String key, String format) {
try {
return new SimpleDateFormat(format).parse(getString(key));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** 转为Date并返回根据格式 yyyy-MM-dd */
public Date getDate(String key) {
return getDateByFormat(key, "yyyy-MM-dd");
}
/** 转为Date并返回根据格式 yyyy-MM-dd HH:mm:ss */
public Date getDateTime(String key) {
return getDateByFormat(key, "yyyy-MM-dd HH:mm:ss");
}
/** 获取集合(必须原先就是个集合,否则会创建个新集合并返回) */
@SuppressWarnings("unchecked")
public List<Object> getList(String key) {
Object value = get(key);
List<Object> list = null;
if(value == null || value.equals("")) {
list = new ArrayList<Object>();
}
else if(value instanceof List) {
list = (List<Object>)value;
} else {
list = new ArrayList<Object>();
list.add(value);
}
return list;
}
/** 获取集合 (指定泛型类型) */
public <T> List<T> getList(String key, Class<T> cs) {
List<Object> list = getList(key);
List<T> list2 = new ArrayList<T>();
for (Object obj : list) {
T objC = getValueByClass(obj, cs);
list2.add(objC);
}
return list2;
}
/** 获取集合(逗号分隔式)(指定类型) */
public <T> List<T> getListByComma(String key, Class<T> cs) {
String listStr = getString(key);
if(listStr == null || listStr.equals("")) {
return new ArrayList<>();
}
// 开始转化
String [] arr = listStr.split(",");
List<T> list = new ArrayList<T>();
for (String str : arr) {
if(cs == int.class || cs == Integer.class || cs == long.class || cs == Long.class) {
str = str.trim();
}
T objC = getValueByClass(str, cs);
list.add(objC);
}
return list;
}
/** 根据指定类型从map中取值返回实体对象 */
public <T> T getModel(Class<T> cs) {
try {
return getModelByObject(cs.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** 从map中取值塞到一个对象中 */
public <T> T getModelByObject(T obj) {
// 获取类型
Class<?> cs = obj.getClass();
// 循环复制
for (Field field : cs.getDeclaredFields()) {
try {
// 获取对象
Object value = this.get(field.getName());
if(value == null) {
continue;
}
field.setAccessible(true);
Object valueConvert = getValueByClass(value, field.getType());
field.set(obj, valueConvert);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("属性取值出错:" + field.getName(), e);
}
}
return obj;
}
/**
* 将指定值转化为指定类型并返回
* @param obj
* @param cs
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getValueByClass(Object obj, Class<T> cs) {
String obj2 = String.valueOf(obj);
Object obj3 = null;
if (cs.equals(String.class)) {
obj3 = obj2;
} else if (cs.equals(int.class) || cs.equals(Integer.class)) {
obj3 = Integer.valueOf(obj2);
} else if (cs.equals(long.class) || cs.equals(Long.class)) {
obj3 = Long.valueOf(obj2);
} else if (cs.equals(short.class) || cs.equals(Short.class)) {
obj3 = Short.valueOf(obj2);
} else if (cs.equals(byte.class) || cs.equals(Byte.class)) {
obj3 = Byte.valueOf(obj2);
} else if (cs.equals(float.class) || cs.equals(Float.class)) {
obj3 = Float.valueOf(obj2);
} else if (cs.equals(double.class) || cs.equals(Double.class)) {
obj3 = Double.valueOf(obj2);
} else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) {
obj3 = Boolean.valueOf(obj2);
} else {
obj3 = (T)obj;
}
return (T)obj3;
}
// ============================= 写值 =============================
/**
* 给指定key添加一个默认值只有在这个key原来无值的情况先才会set进去
*/
public void setDefaultValue(String key, Object defaultValue) {
if(isNull(key)) {
set(key, defaultValue);
}
}
/** set一个值连缀风格 */
public SoMap set(String key, Object value) {
// 防止敏感key
if(key.toLowerCase().equals("this")) {
return this;
}
put(key, value);
return this;
}
/** 将一个Map塞进SoMap */
public SoMap setMap(Map<String, ?> map) {
if(map != null) {
for (String key : map.keySet()) {
this.set(key, map.get(key));
}
}
return this;
}
/** 将一个对象解析塞进SoMap */
public SoMap setModel(Object model) {
if(model == null) {
return this;
}
Field[] fields = model.getClass().getDeclaredFields();
for (Field field : fields) {
try{
field.setAccessible(true);
boolean isStatic = Modifier.isStatic(field.getModifiers());
if(!isStatic) {
this.set(field.getName(), field.get(model));
}
}catch (Exception e){
throw new RuntimeException(e);
}
}
return this;
}
/** 将json字符串解析后塞进SoMap */
public SoMap setJsonString(String jsonString) {
try {
@SuppressWarnings("unchecked")
Map<String, Object> map = new ObjectMapper().readValue(jsonString, Map.class);
return this.setMap(map);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// ============================= 删值 =============================
/** delete一个值连缀风格 */
public SoMap delete(String key) {
remove(key);
return this;
}
/** 清理所有value为null的字段 */
public SoMap clearNull() {
Iterator<String> iterator = this.keySet().iterator();
while(iterator.hasNext()) {
String key = iterator.next();
if(this.isNull(key)) {
iterator.remove();
this.remove(key);
}
}
return this;
}
/** 清理指定key */
public SoMap clearIn(String ...keys) {
List<String> keys2 = Arrays.asList(keys);
Iterator<String> iterator = this.keySet().iterator();
while(iterator.hasNext()) {
String key = iterator.next();
if(keys2.contains(key) == true) {
iterator.remove();
this.remove(key);
}
}
return this;
}
/** 清理掉不在列表中的key */
public SoMap clearNotIn(String ...keys) {
List<String> keys2 = Arrays.asList(keys);
Iterator<String> iterator = this.keySet().iterator();
while(iterator.hasNext()) {
String key = iterator.next();
if(keys2.contains(key) == false) {
iterator.remove();
this.remove(key);
}
}
return this;
}
/** 清理掉所有key */
public SoMap clearAll() {
clear();
return this;
}
// ============================= 快速构建 =============================
/** 构建一个SoMap并返回 */
public static SoMap getSoMap() {
return new SoMap();
}
/** 构建一个SoMap并返回 */
public static SoMap getSoMap(String key, Object value) {
return new SoMap().set(key, value);
}
/** 构建一个SoMap并返回 */
public static SoMap getSoMap(Map<String, ?> map) {
return new SoMap().setMap(map);
}
/** 将一个对象集合解析成为SoMap */
public static SoMap getSoMapByModel(Object model) {
return SoMap.getSoMap().setModel(model);
}
/** 将一个对象集合解析成为SoMap集合 */
public static List<SoMap> getSoMapByList(List<?> list) {
List<SoMap> listMap = new ArrayList<SoMap>();
for (Object model : list) {
listMap.add(getSoMapByModel(model));
}
return listMap;
}
/** 克隆指定key返回一个新的SoMap */
public SoMap cloneKeys(String... keys) {
SoMap so = new SoMap();
for (String key : keys) {
so.set(key, this.get(key));
}
return so;
}
/** 克隆所有key返回一个新的SoMap */
public SoMap cloneSoMap() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(key, this.get(key));
}
return so;
}
/** 将所有key转为大写 */
public SoMap toUpperCase() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(key.toUpperCase(), this.get(key));
}
this.clearAll().setMap(so);
return this;
}
/** 将所有key转为小写 */
public SoMap toLowerCase() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(key.toLowerCase(), this.get(key));
}
this.clearAll().setMap(so);
return this;
}
/** 将所有key中下划线转为中划线模式 (kebab-case风格) */
public SoMap toKebabCase() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(wordEachKebabCase(key), this.get(key));
}
this.clearAll().setMap(so);
return this;
}
/** 将所有key中下划线转为小驼峰模式 */
public SoMap toHumpCase() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(wordEachBigFs(key), this.get(key));
}
this.clearAll().setMap(so);
return this;
}
/** 将所有key中小驼峰转为下划线模式 */
public SoMap humpToLineCase() {
SoMap so = new SoMap();
for (String key : this.keySet()) {
so.set(wordHumpToLine(key), this.get(key));
}
this.clearAll().setMap(so);
return this;
}
// ============================= 辅助方法 =============================
/** 指定key是否为null判定标准为 NULL_ELEMENT_ARRAY 中的元素 */
public boolean isNull(String key) {
return valueIsNull(get(key));
}
/** 指定key列表中是否包含value为null的元素只要有一个为null就会返回true */
public boolean isContainNull(String ...keys) {
for (String key : keys) {
if(this.isNull(key)) {
return true;
}
}
return false;
}
/** 与isNull()相反 */
public boolean isNotNull(String key) {
return !isNull(key);
}
/** 指定key的value是否为null作用同isNotNull() */
public boolean has(String key) {
return !isNull(key);
}
/** 指定value在此SoMap的判断标准中是否为null */
public boolean valueIsNull(Object value) {
return NULL_ELEMENT_LIST.contains(value);
}
/** 验证指定key不为空为空则抛出异常 */
public SoMap checkNull(String ...keys) {
for (String key : keys) {
if(this.isNull(key)) {
throw new RuntimeException("参数" + key + "不能为空");
}
}
return this;
}
static Pattern patternNumber = Pattern.compile("[0-9]*");
/** 指定key是否为数字 */
public boolean isNumber(String key) {
String value = getString(key);
if(value == null) {
return false;
}
return patternNumber.matcher(value).matches();
}
/**
* 转为JSON字符串
*/
public String toJsonString() {
try {
// SoMap so = SoMap.getSoMap(this);
return new ObjectMapper().writeValueAsString(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//
// /**
// * 转为JSON字符串, 带格式的
// */
// public String toJsonFormatString() {
// try {
// return JSON.toJSONString(this, true);
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
// ============================= web辅助 =============================
/**
* 返回当前request请求的的所有参数
* @return
*/
public static SoMap getRequestSoMap() {
// 大善人SpringMVC提供的封装
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes == null) {
throw new RuntimeException("当前线程非JavaWeb环境");
}
// 当前request
HttpServletRequest request = servletRequestAttributes.getRequest();
if (request.getAttribute("currentSoMap") == null || request.getAttribute("currentSoMap") instanceof SoMap == false ) {
initRequestSoMap(request);
}
return (SoMap)request.getAttribute("currentSoMap");
}
/** 初始化当前request的 SoMap */
private static void initRequestSoMap(HttpServletRequest request) {
SoMap soMap = new SoMap();
Map<String, String[]> parameterMap = request.getParameterMap(); // 获取所有参数
for (String key : parameterMap.keySet()) {
try {
String[] values = parameterMap.get(key); // 获得values
if(values.length == 1) {
soMap.set(key, values[0]);
} else {
List<String> list = new ArrayList<String>();
for (String v : values) {
list.add(v);
}
soMap.set(key, list);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
request.setAttribute("currentSoMap", soMap);
}
/**
* 验证返回当前线程是否为JavaWeb环境
* @return
*/
public static boolean isJavaWeb() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装
if(servletRequestAttributes == null) {
return false;
}
return true;
}
// ============================= 常见key 以下key经常用所以封装以下方便写代码 =============================
/** get 当前页 */
public int getKeyPageNo() {
int pageNo = getInt("pageNo", 1);
if(pageNo <= 0) {
pageNo = 1;
}
return pageNo;
}
/** get 页大小 */
public int getKeyPageSize() {
int pageSize = getInt("pageSize", 10);
if(pageSize <= 0 || pageSize > 1000) {
pageSize = 10;
}
return pageSize;
}
/** get 排序方式 */
public int getKeySortType() {
return getInt("sortType");
}
// ============================= 分页相关(封装mybatis的page-help插件 ) =============================
// /** 分页插件 */
// private com.github.pagehelper.Page<?> pagePlug;
// /** 分页插件 - 开始分页 */
// public SoMap startPage() {
// this.pagePlug= com.github.pagehelper.PageHelper.startPage(getKeyPageNo(), getKeyPageSize());
// return this;
// }
// /** 获取上次分页的记录总数 */
// public long getDataCount() {
// if(pagePlug == null) {
// return -1;
// }
// return pagePlug.getTotal();
// }
// /** 分页插件 - 结束分页, 返回总条数 该方法已过时请调用更加符合语义化的getDataCount() */
// @Deprecated
// public long endPage() {
// return getDataCount();
// }
// ============================= 工具方法 =============================
/**
* 将一个一维集合转换为树形集合
* @param list 集合
* @param idKey id标识key
* @param parentIdKey 父id标识key
* @param childListKey 子节点标识key
* @return 转换后的tree集合
*/
public static List<SoMap> listToTree(List<SoMap> list, String idKey, String parentIdKey, String childListKey) {
// 声明新的集合存储tree形数据
List<SoMap> newTreeList = new ArrayList<SoMap>();
// 声明hash-Map方便查找数据
SoMap hash = new SoMap();
// 将数组转为Object的形式key为数组中的id
for (int i = 0; i < list.size(); i++) {
SoMap json = (SoMap) list.get(i);
hash.put(json.getString(idKey), json);
}
// 遍历结果集
for (int j = 0; j < list.size(); j++) {
// 单条记录
SoMap aVal = (SoMap) list.get(j);
// 在hash中取出key为单条记录中pid的值
SoMap hashVp = (SoMap) hash.get(aVal.get(parentIdKey, "").toString());
// 如果记录的pid存在则说明它有父节点将她添加到孩子节点的集合中
if (hashVp != null) {
// 检查是否有child属性有则添加没有则新建
if (hashVp.get(childListKey) != null) {
@SuppressWarnings("unchecked")
List<SoMap> ch = (List<SoMap>) hashVp.get(childListKey);
ch.add(aVal);
hashVp.put(childListKey, ch);
} else {
List<SoMap> ch = new ArrayList<SoMap>();
ch.add(aVal);
hashVp.put(childListKey, ch);
}
} else {
newTreeList.add(aVal);
}
}
return newTreeList;
}
/** 指定字符串的字符串下划线转大写模式 */
private static String wordEachBig(String str){
String newStr = "";
for (String s : str.split("_")) {
newStr += wordFirstBig(s);
}
return newStr;
}
/** 返回下划线转小驼峰形式 */
private static String wordEachBigFs(String str){
return wordFirstSmall(wordEachBig(str));
}
/** 将指定单词首字母大写 */
private static String wordFirstBig(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
}
/** 将指定单词首字母小写 */
private static String wordFirstSmall(String str) {
return str.substring(0, 1).toLowerCase() + str.substring(1, str.length());
}
/** 下划线转中划线 */
private static String wordEachKebabCase(String str) {
return str.replaceAll("_", "-");
}
/** 驼峰转下划线 */
private static String wordHumpToLine(String str) {
return str.replaceAll("[A-Z]", "_$0").toLowerCase();
}
}

View File

@@ -0,0 +1,16 @@
package cn.dev33.satoken.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
* @author Auster
*
*/
@SpringBootApplication
public class StartUpApplication {
public static void main(String[] args) {
SpringApplication.run(StartUpApplication.class, args);
}
}

View File

@@ -1,4 +1,4 @@
package com.pj.test.satoken;
package cn.dev33.satoken.springboot.satoken;
import java.util.Arrays;
import java.util.List;