寫在最前
如果這個項目讓你有所收獲,記得 Star 關注哦,這對我是非常不錯的鼓勵與支持。
源碼地址(后端):https://gitee.com/csps/mingyue
源碼地址(前端):https://gitee.com/csps/mingyue-ui
文檔地址:https://gitee.com/csps/mingyue/wikis
密碼加密
密碼加密是安全認證不可或缺的部分, Sa-Token
在 v1.14 版本添加密碼加密模塊,該模塊非常簡單,僅僅封裝了一些常見的加密算法。
本系統將采用 BCrypt加密
加密方式對密碼加密!!!
摘要加密
md5、sha1、sha256
// md5加密
SaSecureUtil.md5("123456");// sha1加密
SaSecureUtil.sha1("123456");// sha256加密
SaSecureUtil.sha256("123456");
對稱加密
AES加密
// 定義秘鑰和明文
String key = "123456";
String text = "Sa-Token 一個輕量級java權限認證框架";// 加密
String ciphertext = SaSecureUtil.aesEncrypt(key, text);
System.out.println("AES加密后:" + ciphertext);// 解密
String text2 = SaSecureUtil.aesDecrypt(key, ciphertext);
System.out.println("AES解密后:" + text2);
非對稱加密
RSA加密
// 定義私鑰和公鑰
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);
System.out.println("公鑰加密后:" + ciphertext);// 使用私鑰解密
String text2 = SaSecureUtil.rsaDecryptByPrivate(privateKey, ciphertext);
System.out.println("私鑰解密后:" + text2);
私鑰和公鑰調用以下方法生成即可
// 生成一對公鑰和私鑰,其中Map對象 (private=私鑰, public=公鑰)
System.out.println(SaSecureUtil.rsaGenerateKeyPair());
Base64編碼與解碼
// 文本
String text = "Sa-Token 一個輕量級java權限認證框架";// 使用Base64編碼
String base64Text = SaBase64Util.encode(text);
System.out.println("Base64編碼后:" + base64Text);// 使用Base64解碼
String text2 = SaBase64Util.decode(base64Text);
System.out.println("Base64解碼后:" + text2);
BCrypt加密
由它加密的文件可在所有支持的操作系統和處理器上進行轉移
// 使用方法
String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); // 使用checkpw方法檢查被加密的字符串是否與原始字符串匹配:
BCrypt.checkpw(candidate_password, stored_hash); // gensalt方法提供了可選參數 (log_rounds) 來定義加鹽多少,也決定了加密的復雜度:
String strong_salt = BCrypt.gensalt(10);
String stronger_salt = BCrypt.gensalt(12);
密文登錄
1. 明文密碼生成密文
// 生成加密鹽
String gensalt = BCrypt.gensalt();String pw_hash = BCrypt.hashpw("123456", gensalt); // 打印加密后的密文
System.out.println(pw_hash);
// $2a$12$pBVti6NTcVJxptxHNqetBewxqwJU54.sItx3b8U2Kl44XnQinfUHq
2. 生成加密鹽放入 Nacos
mingyue-auth.yml
# 用戶配置
user:password:# 私鑰salt: $2a$12$pBVti6NTcVJxptxHNqetBe
用戶密碼配置類
@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "user.password")
public class UserPasswordProperties {/*** 密碼加鹽*/private String salt;}
3. 修改數據庫用戶密碼
INSERT INTO `sys_user` VALUES (1, 'mingyue', '明月', '0', '$2a$12$pBVti6NTcVJxptxHNqetBewxqwJU54.sItx3b8U2Kl44XnQinfUHq', '13288888888', NULL, NULL, '0', '0', '2023-07-19 17:06:22', '2023-07-19 17:06:25', 'mingyue', 'mingyue');
INSERT INTO `sys_user` VALUES (2, 'strive', 'Strive', '0', '$2a$12$pBVti6NTcVJxptxHNqetBewxqwJU54.sItx3b8U2Kl44XnQinfUHq', '15388888888', NULL, NULL, '0', '0', '2023-07-19 17:06:22', '2023-07-19 17:06:25', 'mingyue', 'mingyue');
4. 修改登錄密碼校驗
public SaTokenInfo login(PasswordLoginDto dto) {// 遠程調用用戶服務R<LoginUser> userInfoResp = remoteUserService.userInfo(dto.getUsername());if (Objects.isNull(userInfoResp) || Objects.isNull(userInfoResp.getData())) {return null;}LoginUser userInfo = userInfoResp.getData();// 登錄密碼校驗if (!userInfo.getPassword().equals(dto.getPassword())) {throw new UserException("密碼錯誤,請重試!");}if (dto.getUsername().equals(userInfo.getUsername()) && dto.getPassword().equals(userInfo.getPassword())) {// 第1步,先登錄上LoginHelper.login(userInfo);// 第2步,獲取 Token 相關參數SaTokenInfo tokenInfo = StpUtil.getTokenInfo();return tokenInfo;}return null;}
5.啟動測試
5.1. 明文測試
curl -X 'POST' \'http://mingyue-gateway:9100/auth/login' \-H 'accept: */*' \-H 'Content-Type: application/json' \-d '{"username": "mingyue","password": "123456"
}'
測試結果
{"code": 500,"msg": "密碼錯誤,請重試!","data": null
}
5.2. 密文測試
curl -X 'POST' \'http://mingyue-gateway:9100/auth/login' \-H 'accept: */*' \-H 'Content-Type: application/json' \-d '{"username": "mingyue","password": "$2a$12$pBVti6NTcVJxptxHNqetBewxqwJU54.sItx3b8U2Kl44XnQinfUHq"
}'
測試結果
{"code": 200,"msg": "登錄成功","data": "nHefN9Z9t3bptgQ5CI3nMMqPuCEOS03n"
}
MingYue-UI登錄修改
明文轉密文
state.ruleForm.password = bcryptjs.hashSync(state.ruleForm.password, state.salt);
const onSignIn = async () => {state.loading.signIn = true;state.ruleForm.password = bcryptjs.hashSync(state.ruleForm.password, state.salt);useLoginApi().signIn(state.ruleForm).then(async res => {// 存儲 token 到瀏覽器緩存Session.set('token', res.data);// 模擬數據,對接接口時,記得刪除多余代碼及對應依賴的引入。用于 `/src/stores/userInfo.ts` 中不同用戶登錄判斷(模擬數據)Cookies.set('username', state.ruleForm.username);if (!themeConfig.value.isRequestRoutes) {// 前端控制路由,2、請注意執行順序const isNoPower = await initFrontEndControlRoutes();signInSuccess(isNoPower);} else {// 模擬后端控制路由,isRequestRoutes 為 true,則開啟后端控制路由// 添加完動態路由,再進行 router 跳轉,否則可能報錯 No match found for location with path "/"const isNoPower = await initBackEndControlRoutes();// 執行完 initBackEndControlRoutes,再執行 signInSuccesssignInSuccess(isNoPower);}});};
小結
現在終于不是明文登錄啦~
目前 mingyue-ui
的登錄驗證碼還是固定的,接下來,我們需要把驗證碼用上,沖!