mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: Added password encryption for login functionality (#7764)
This commit is contained in:
parent
4f57dfc76e
commit
aaaa5980b5
@ -15,6 +15,7 @@ type DBOption func(*gorm.DB) *gorm.DB
|
||||
type ICommonRepo interface {
|
||||
WithByID(id uint) DBOption
|
||||
WithByName(name string) DBOption
|
||||
WithByLowerName(name string) DBOption
|
||||
WithByType(tp string) DBOption
|
||||
WithOrderBy(orderStr string) DBOption
|
||||
WithOrderRuleBy(orderBy, order string) DBOption
|
||||
@ -45,6 +46,12 @@ func (c *CommonRepo) WithByName(name string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByLowerName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("LOWER(name) = LOWER(?)", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByDate(startTime, endTime time.Time) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("start_time > ? AND start_time < ?", startTime, endTime)
|
||||
|
@ -16,6 +16,7 @@ type ISettingRepo interface {
|
||||
Create(key, value string) error
|
||||
Update(key, value string) error
|
||||
WithByKey(key string) DBOption
|
||||
UpdateOrCreate(key, value string) error
|
||||
|
||||
CreateMonitorBase(model model.MonitorBase) error
|
||||
BatchCreateMonitorIO(ioList []model.MonitorIO) error
|
||||
@ -85,3 +86,7 @@ func (u *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
|
||||
func (u *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
}
|
||||
|
||||
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Assign(model.Setting{Key: key, Value: value}).FirstOrCreate(&model.Setting{}).Error
|
||||
}
|
||||
|
@ -326,7 +326,8 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
|
||||
err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
|
||||
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByLowerName(req.Name)); len(list) > 0 {
|
||||
err = buserr.New(constant.ErrAppNameExist)
|
||||
return
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package service
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"encoding/base64"
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
@ -15,6 +13,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type AuthService struct{}
|
||||
@ -38,16 +37,11 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*d
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
if nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
if err = checkPassword(info.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
if err != nil {
|
||||
@ -83,17 +77,12 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
if nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
if err = checkPassword(info.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -219,3 +208,28 @@ func (u *AuthService) IsLogin(c *gin.Context) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func checkPassword(password string) error {
|
||||
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
|
||||
|
||||
privateKey, err := encrypt.ParseRSAPrivateKey(priKey.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
loginPassword, err := encrypt.DecryptPassword(password, privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
existPassword, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hmac.Equal([]byte(loginPassword), []byte(existPassword)) {
|
||||
return constant.ErrAuth
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
@ -42,6 +44,7 @@ type ISettingService interface {
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
GenerateApiKey() (string, error)
|
||||
UpdateApiConfig(req dto.ApiInterfaceConfig) error
|
||||
GenerateRSAKey() error
|
||||
}
|
||||
|
||||
func NewISettingService() ISettingService {
|
||||
@ -516,3 +519,47 @@ func (u *SettingService) UpdateApiConfig(req dto.ApiInterfaceConfig) error {
|
||||
global.CONF.System.ApiKeyValidityTime = req.ApiKeyValidityTime
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportPrivateKeyToPEM(privateKey *rsa.PrivateKey) string {
|
||||
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: privateKeyBytes,
|
||||
})
|
||||
return string(privateKeyPEM)
|
||||
}
|
||||
|
||||
func exportPublicKeyToPEM(publicKey *rsa.PublicKey) (string, error) {
|
||||
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: publicKeyBytes,
|
||||
})
|
||||
return string(publicKeyPEM), nil
|
||||
}
|
||||
|
||||
func (u *SettingService) GenerateRSAKey() error {
|
||||
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
|
||||
pubKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PUBLIC_KEY"))
|
||||
if priKey.Value != "" && pubKey.Value != "" {
|
||||
return nil
|
||||
}
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
privateKeyPEM := exportPrivateKeyToPEM(privateKey)
|
||||
publicKeyPEM, err := exportPublicKeyToPEM(&privateKey.PublicKey)
|
||||
err = settingRepo.UpdateOrCreate("PASSWORD_PRIVATE_KEY", privateKeyPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = settingRepo.UpdateOrCreate("PASSWORD_PUBLIC_KEY", publicKeyPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ func Init() {
|
||||
go syncInstalledApp()
|
||||
go syncRuntime()
|
||||
go syncSSL()
|
||||
generateKey()
|
||||
}
|
||||
|
||||
func syncApp() {
|
||||
@ -38,3 +39,9 @@ func syncSSL() {
|
||||
global.LOG.Errorf("sync ssl status error : %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func generateKey() {
|
||||
if err := service.NewISettingService().GenerateRSAKey(); err != nil {
|
||||
global.LOG.Errorf("generate rsa key error : %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
@ -113,9 +113,7 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
||||
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
|
||||
rootRouter.Static("/api/v1/images", "./uploads")
|
||||
rootRouter.Use(func(c *gin.Context) {
|
||||
c.Next()
|
||||
})
|
||||
|
||||
rootRouter.GET("/assets/*filepath", func(c *gin.Context) {
|
||||
c.Writer.Header().Set("Cache-Control", fmt.Sprintf("private, max-age=%d", 3600))
|
||||
staticServer := http.FileServer(http.FS(web.Assets))
|
||||
@ -158,6 +156,7 @@ func Routers() *gin.Engine {
|
||||
|
||||
Router.Use(middleware.WhiteAllow())
|
||||
Router.Use(middleware.BindDomain())
|
||||
Router.Use(middleware.SetPasswordPublicKey())
|
||||
|
||||
Router.NoRoute(func(c *gin.Context) {
|
||||
if checkFrontendPath(c) {
|
||||
|
22
backend/middleware/password_rsa.go
Normal file
22
backend/middleware/password_rsa.go
Normal file
@ -0,0 +1,22 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func SetPasswordPublicKey() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
cookieKey, _ := c.Cookie("panel_public_key")
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
key, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PUBLIC_KEY"))
|
||||
base64Key := base64.StdEncoding.EncodeToString([]byte(key.Value))
|
||||
if base64Key == cookieKey {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
c.SetCookie("panel_public_key", base64Key, 7*24*60*60, "/", "", false, false)
|
||||
c.Next()
|
||||
}
|
||||
}
|
@ -5,9 +5,14 @@ import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
@ -102,3 +107,75 @@ func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) {
|
||||
ciphertext = unPadding(ciphertext)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func ParseRSAPrivateKey(privateKeyPEM string) (*rsa.PrivateKey, error) {
|
||||
block, _ := pem.Decode([]byte(privateKeyPEM))
|
||||
if block == nil || block.Type != "RSA PRIVATE KEY" {
|
||||
return nil, errors.New("failed to decode PEM block containing the private key")
|
||||
}
|
||||
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func aesDecrypt(ciphertext, key, iv []byte) ([]byte, error) {
|
||||
if len(key) != 16 && len(key) != 24 && len(key) != 32 {
|
||||
return nil, errors.New("invalid AES key length: must be 16, 24, or 32 bytes")
|
||||
}
|
||||
if len(iv) != aes.BlockSize {
|
||||
return nil, errors.New("invalid IV length: must be 16 bytes")
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(ciphertext, ciphertext)
|
||||
ciphertext = pkcs7Unpad(ciphertext)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func pkcs7Unpad(data []byte) []byte {
|
||||
length := len(data)
|
||||
padLength := int(data[length-1])
|
||||
return data[:length-padLength]
|
||||
}
|
||||
|
||||
func DecryptPassword(encryptedData string, privateKey *rsa.PrivateKey) (string, error) {
|
||||
parts := strings.Split(encryptedData, ":")
|
||||
if len(parts) != 3 {
|
||||
return "", errors.New("encrypted data format error")
|
||||
}
|
||||
keyCipher := parts[0]
|
||||
ivBase64 := parts[1]
|
||||
ciphertextBase64 := parts[2]
|
||||
|
||||
encryptedAESKey, err := base64.StdEncoding.DecodeString(keyCipher)
|
||||
if err != nil {
|
||||
return "", errors.New("failed to decode keyCipher")
|
||||
}
|
||||
|
||||
aesKey, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, encryptedAESKey)
|
||||
if err != nil {
|
||||
return "", errors.New("failed to decode AES Key")
|
||||
}
|
||||
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(ciphertextBase64)
|
||||
if err != nil {
|
||||
return "", errors.New("failed to decrypt the encrypted data")
|
||||
}
|
||||
iv, err := base64.StdEncoding.DecodeString(ivBase64)
|
||||
if err != nil {
|
||||
return "", errors.New("failed to decode the IV")
|
||||
}
|
||||
|
||||
password, err := aesDecrypt(ciphertext, aesKey, iv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(password), nil
|
||||
}
|
||||
|
@ -21,9 +21,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-php": "^6.0.1",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/language": "^6.10.2",
|
||||
"@codemirror/legacy-modes": "^6.4.0",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
@ -37,11 +37,13 @@
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"axios": "^1.7.2",
|
||||
"codemirror": "^6.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.7.5",
|
||||
"fit2cloud-ui-plus": "^1.2.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"js-base64": "^3.7.7",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"md-editor-v3": "^2.11.3",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"nprogress": "^0.2.0",
|
||||
@ -54,11 +56,12 @@
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-demi": "^0.14.6",
|
||||
"vue-i18n": "^10.0.5",
|
||||
"vue-router": "^4.3.3"
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.3.3",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/node": "^20.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.22.0",
|
||||
"@typescript-eslint/parser": "^5.22.0",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
@ -73,7 +76,7 @@
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-html": "^1.4.1",
|
||||
"prettier": "^2.6.2",
|
||||
"rollup-plugin-visualizer": "^5.5.4",
|
||||
"rollup-plugin-visualizer": "^5.14.0",
|
||||
"sass": "^1.77.8",
|
||||
"standard-version": "^9.5.0",
|
||||
"stylelint": "^15.10.1",
|
||||
@ -81,7 +84,7 @@
|
||||
"typescript": "^4.5.4",
|
||||
"unplugin-auto-import": "^0.16.4",
|
||||
"unplugin-vue-components": "^0.25.0",
|
||||
"vite": "^5.2.13",
|
||||
"vite": "^6.0.7",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
@ -90,7 +93,7 @@
|
||||
"vue-tsc": "^0.29.8"
|
||||
},
|
||||
"overrides": {
|
||||
"esbuild": "npm:esbuild-wasm@latest"
|
||||
"esbuild": "npm:esbuild-wasm@0.24.2"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
@ -289,7 +289,7 @@ const checkAppName = (rule: any, value: any, callback: any) => {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback(new Error(i18n.global.t('commons.rule.appName')));
|
||||
} else {
|
||||
const reg = /^(?![_-])[a-z0-9_-]{1,29}[a-zA-Z0-9]$/;
|
||||
const reg = /^(?![_-])[a-zA-Z0-9_-]{1,29}[a-zA-Z0-9]$/;
|
||||
if (!reg.test(value) && value !== '') {
|
||||
callback(new Error(i18n.global.t('commons.rule.appName')));
|
||||
} else {
|
||||
|
@ -1451,8 +1451,7 @@ const message = {
|
||||
confDockerProxy: 'Configurar proxy do Docker',
|
||||
restartNowHelper: 'Configurar o proxy do Docker exige reiniciar o serviço Docker.',
|
||||
restartNow: 'Reiniciar imediatamente',
|
||||
systemIPWarning:
|
||||
'O endereço do sistema não está definido no momento. Defina-o primeiro no painel de controle.',
|
||||
systemIPWarning: 'O endereço do sistema não está definido no momento. Defina-o primeiro no painel de controle.',
|
||||
systemIPWarning1:
|
||||
'O endereço do sistema atual está definido como {0}, e o redirecionamento rápido não é possível!',
|
||||
defaultNetwork: 'Placa de rede',
|
||||
|
@ -3,6 +3,8 @@ import i18n from '@/lang';
|
||||
import useClipboard from 'vue-clipboard3';
|
||||
const { toClipboard } = useClipboard();
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import JSEncrypt from 'jsencrypt';
|
||||
import CryptoJS from 'crypto-js';
|
||||
|
||||
export function deepCopy<T>(obj: any): T {
|
||||
let newObj: any;
|
||||
@ -615,3 +617,61 @@ export const escapeProxyURL = (url: string): string => {
|
||||
|
||||
return url.replace(/[\/:?#[\]@!$&'()*+,;=%~]/g, (match) => encodeMap[match] || match);
|
||||
};
|
||||
|
||||
function getCookie(name: string) {
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
if (parts.length === 2) return parts.pop().split(';').shift();
|
||||
}
|
||||
|
||||
function rsaEncrypt(data: string, publicKey: string) {
|
||||
if (!data) {
|
||||
return data;
|
||||
}
|
||||
const jsEncrypt = new JSEncrypt();
|
||||
jsEncrypt.setPublicKey(publicKey);
|
||||
return jsEncrypt.encrypt(data);
|
||||
}
|
||||
|
||||
function aesEncrypt(data: string, key: string) {
|
||||
const keyBytes = CryptoJS.enc.Utf8.parse(key);
|
||||
const iv = CryptoJS.lib.WordArray.random(16);
|
||||
const encrypted = CryptoJS.AES.encrypt(data, keyBytes, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
return iv.toString(CryptoJS.enc.Base64) + ':' + encrypted.toString();
|
||||
}
|
||||
|
||||
function urlDecode(value: string): string {
|
||||
return decodeURIComponent(value.replace(/\+/g, ' '));
|
||||
}
|
||||
|
||||
function generateAESKey(): string {
|
||||
const keyLength = 16;
|
||||
const randomBytes = new Uint8Array(keyLength);
|
||||
crypto.getRandomValues(randomBytes);
|
||||
return Array.from(randomBytes)
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
}
|
||||
|
||||
export const encryptPassword = (password: string) => {
|
||||
if (!password) {
|
||||
return '';
|
||||
}
|
||||
let rsaPublicKeyText = getCookie('panel_public_key');
|
||||
if (!rsaPublicKeyText) {
|
||||
console.log('RSA public key not found');
|
||||
return password;
|
||||
}
|
||||
rsaPublicKeyText = urlDecode(rsaPublicKeyText);
|
||||
|
||||
const aesKey = generateAESKey();
|
||||
rsaPublicKeyText = rsaPublicKeyText.replaceAll('"', '');
|
||||
const rsaPublicKey = atob(rsaPublicKeyText);
|
||||
const keyCipher = rsaEncrypt(aesKey, rsaPublicKey);
|
||||
const passwordCipher = aesEncrypt(password, aesKey);
|
||||
return `${keyCipher}:${passwordCipher}`;
|
||||
};
|
||||
|
@ -180,6 +180,7 @@ import { MsgSuccess } from '@/utils/message';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { getSettingInfo } from '@/api/modules/setting';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { encryptPassword } from '@/utils/util';
|
||||
|
||||
const i18n = useI18n();
|
||||
const themeConfig = computed(() => globalStore.themeConfig);
|
||||
@ -314,7 +315,7 @@ const login = (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
let requestLoginForm = {
|
||||
name: loginForm.name,
|
||||
password: loginForm.password,
|
||||
password: encryptPassword(loginForm.password),
|
||||
ignoreCaptcha: globalStore.ignoreCaptcha,
|
||||
captcha: loginForm.captcha,
|
||||
captchaID: captcha.captchaID,
|
||||
@ -370,7 +371,7 @@ const mfaLogin = async (auto: boolean) => {
|
||||
if ((!auto && mfaLoginForm.code) || (auto && mfaLoginForm.code.length === 6)) {
|
||||
isLoggingIn = true;
|
||||
mfaLoginForm.name = loginForm.name;
|
||||
mfaLoginForm.password = loginForm.password;
|
||||
mfaLoginForm.password = encryptPassword(loginForm.password);
|
||||
const res = await mfaLoginApi(mfaLoginForm);
|
||||
if (res.code === 406) {
|
||||
errMfaInfo.value = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user