mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-12 19:40:06 +08:00
feat(system): Password encryption for login API. (#7825)
This commit is contained in:
parent
a86d56bef5
commit
8b30308a4b
@ -37,16 +37,11 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*d
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
if nameSetting.Value != info.Name {
|
||||||
if err != nil {
|
|
||||||
return nil, "", buserr.New("ErrRecordNotFound")
|
|
||||||
}
|
|
||||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "ErrAuth", nil
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
if err = checkPassword(info.Password); err != nil {
|
||||||
return nil, "ErrAuth", nil
|
return nil, "ErrAuth", err
|
||||||
}
|
}
|
||||||
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -77,17 +72,12 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
if nameSetting.Value != info.Name {
|
||||||
if err != nil {
|
|
||||||
return nil, "", buserr.New("ErrRecordNotFound")
|
|
||||||
}
|
|
||||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
|
||||||
return nil, "ErrAuth", nil
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
|
if err = checkPassword(info.Password); err != nil {
|
||||||
|
return nil, "ErrAuth", err
|
||||||
|
}
|
||||||
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
@ -216,3 +206,28 @@ func (u *AuthService) IsLogin(c *gin.Context) bool {
|
|||||||
_, err := global.SESSION.Get(c)
|
_, err := global.SESSION.Get(c)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkPassword(password string) error {
|
||||||
|
priKey, _ := settingRepo.Get(repo.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(repo.WithByKey("Password"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
existPassword, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !hmac.Equal([]byte(loginPassword), []byte(existPassword)) {
|
||||||
|
return buserr.New("ErrAuth")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -45,6 +47,8 @@ type ISettingService interface {
|
|||||||
UpdateTerminal(req dto.TerminalInfo) error
|
UpdateTerminal(req dto.TerminalInfo) error
|
||||||
|
|
||||||
UpdateSystemSSL() error
|
UpdateSystemSSL() error
|
||||||
|
|
||||||
|
GenerateRSAKey() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewISettingService() ISettingService {
|
func NewISettingService() ISettingService {
|
||||||
@ -497,3 +501,29 @@ func checkCertValid() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *SettingService) GenerateRSAKey() error {
|
||||||
|
priKey, _ := settingRepo.Get(repo.WithByKey("PASSWORD_PRIVATE_KEY"))
|
||||||
|
pubKey, _ := settingRepo.Get(repo.WithByKey("PASSWORD_PUBLIC_KEY"))
|
||||||
|
if priKey.Value != "" && pubKey.Value != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
privateKeyPEM := encrypt.ExportPrivateKeyToPEM(privateKey)
|
||||||
|
publicKeyPEM, err := encrypt.ExportPublicKeyToPEM(&privateKey.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hook
|
package hook
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/core/app/service"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||||
@ -29,6 +30,8 @@ func Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUserInfo(global.CONF.Base.ChangeUserInfo, settingRepo)
|
handleUserInfo(global.CONF.Base.ChangeUserInfo, settingRepo)
|
||||||
|
|
||||||
|
generateKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
||||||
@ -68,3 +71,9 @@ func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
|||||||
sudo := cmd.SudoHandleCmd()
|
sudo := cmd.SudoHandleCmd()
|
||||||
_, _ = cmd.Execf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", sudo, global.CONF.Base.ChangeUserInfo)
|
_, _ = cmd.Execf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", sudo, global.CONF.Base.ChangeUserInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateKey() {
|
||||||
|
if err := service.NewISettingService().GenerateRSAKey(); err != nil {
|
||||||
|
global.LOG.Errorf("generate rsa key error : %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -167,6 +167,7 @@ func Routers() *gin.Engine {
|
|||||||
PrivateGroup.Use(middleware.WhiteAllow())
|
PrivateGroup.Use(middleware.WhiteAllow())
|
||||||
PrivateGroup.Use(middleware.BindDomain())
|
PrivateGroup.Use(middleware.BindDomain())
|
||||||
PrivateGroup.Use(middleware.GlobalLoading())
|
PrivateGroup.Use(middleware.GlobalLoading())
|
||||||
|
PrivateGroup.Use(middleware.SetPasswordPublicKey())
|
||||||
for _, router := range rou.RouterGroupApp {
|
for _, router := range rou.RouterGroupApp {
|
||||||
router.InitRouter(PrivateGroup)
|
router.InitRouter(PrivateGroup)
|
||||||
}
|
}
|
||||||
|
22
core/middleware/password_rsa.go
Normal file
22
core/middleware/password_rsa.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/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(repo.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,26 +5,19 @@ import (
|
|||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/core/global"
|
"github.com/1Panel-dev/1Panel/core/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StringEncryptWithBase64(text string) (string, error) {
|
|
||||||
base64Item, err := base64.StdEncoding.DecodeString(text)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
encryptItem, err := StringEncrypt(string(base64Item))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return encryptItem, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringDecryptWithBase64(text string) (string, error) {
|
func StringDecryptWithBase64(text string) (string, error) {
|
||||||
decryptItem, err := StringDecrypt(text)
|
decryptItem, err := StringDecrypt(text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -136,3 +129,95 @@ func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
ciphertext = unPadding(ciphertext)
|
ciphertext = unPadding(ciphertext)
|
||||||
return ciphertext, nil
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
"prettier": "prettier --write ."
|
"prettier": "prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-json": "^6.0.1",
|
|
||||||
"@codemirror/lang-html": "^6.4.9",
|
"@codemirror/lang-html": "^6.4.9",
|
||||||
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/lang-php": "^6.0.1",
|
"@codemirror/lang-php": "^6.0.1",
|
||||||
"@codemirror/language": "^6.10.2",
|
"@codemirror/language": "^6.10.2",
|
||||||
"@codemirror/legacy-modes": "^6.4.0",
|
"@codemirror/legacy-modes": "^6.4.0",
|
||||||
@ -35,11 +35,13 @@
|
|||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"echarts": "^5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"element-plus": "^2.7.5",
|
"element-plus": "^2.7.5",
|
||||||
"fit2cloud-ui-plus": "^1.2.0",
|
"fit2cloud-ui-plus": "^1.2.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
|
"jsencrypt": "^3.3.2",
|
||||||
"md-editor-v3": "^2.11.3",
|
"md-editor-v3": "^2.11.3",
|
||||||
"monaco-editor": "^0.50.0",
|
"monaco-editor": "^0.50.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
@ -4,6 +4,8 @@ import useClipboard from 'vue-clipboard3';
|
|||||||
const { toClipboard } = useClipboard();
|
const { toClipboard } = useClipboard();
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import JSEncrypt from 'jsencrypt';
|
||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
export function deepCopy<T>(obj: any): T {
|
export function deepCopy<T>(obj: any): T {
|
||||||
let newObj: any;
|
let newObj: any;
|
||||||
@ -695,3 +697,61 @@ export function getRuntimeLabel(type: string) {
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}`;
|
||||||
|
};
|
||||||
|
@ -189,6 +189,7 @@ import { GlobalStore, MenuStore, TabsStore } from '@/store';
|
|||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { getSettingInfo } from '@/api/modules/setting';
|
import { getSettingInfo } from '@/api/modules/setting';
|
||||||
|
import { encryptPassword } from '@/utils/util';
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const themeConfig = computed(() => globalStore.themeConfig);
|
const themeConfig = computed(() => globalStore.themeConfig);
|
||||||
@ -313,7 +314,7 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
}
|
}
|
||||||
let requestLoginForm = {
|
let requestLoginForm = {
|
||||||
name: loginForm.name,
|
name: loginForm.name,
|
||||||
password: loginForm.password,
|
password: encryptPassword(loginForm.password),
|
||||||
ignoreCaptcha: globalStore.ignoreCaptcha,
|
ignoreCaptcha: globalStore.ignoreCaptcha,
|
||||||
captcha: loginForm.captcha,
|
captcha: loginForm.captcha,
|
||||||
captchaID: captcha.captchaID,
|
captchaID: captcha.captchaID,
|
||||||
@ -352,7 +353,6 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
globalStore.ignoreCaptcha = false;
|
globalStore.ignoreCaptcha = false;
|
||||||
errCaptcha.value = false;
|
errCaptcha.value = false;
|
||||||
errAuthInfo.value = true;
|
errAuthInfo.value = true;
|
||||||
console.log('11111');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loginVerify();
|
loginVerify();
|
||||||
@ -368,7 +368,7 @@ const mfaLogin = async (auto: boolean) => {
|
|||||||
if ((!auto && mfaLoginForm.code) || (auto && mfaLoginForm.code.length === 6)) {
|
if ((!auto && mfaLoginForm.code) || (auto && mfaLoginForm.code.length === 6)) {
|
||||||
isLoggingIn = true;
|
isLoggingIn = true;
|
||||||
mfaLoginForm.name = loginForm.name;
|
mfaLoginForm.name = loginForm.name;
|
||||||
mfaLoginForm.password = loginForm.password;
|
mfaLoginForm.password = encryptPassword(loginForm.password);
|
||||||
try {
|
try {
|
||||||
await mfaLoginApi(mfaLoginForm);
|
await mfaLoginApi(mfaLoginForm);
|
||||||
globalStore.setLogStatus(true);
|
globalStore.setLogStatus(true);
|
||||||
@ -464,173 +464,3 @@ onMounted(() => {
|
|||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<!-- <style scoped lang='scss' > .login-form {
|
|
||||||
padding: 0 40px;
|
|
||||||
.hide {
|
|
||||||
width: 0;
|
|
||||||
border: 0;
|
|
||||||
position: absolute;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
font-size: 30px;
|
|
||||||
letter-spacing: 0;
|
|
||||||
text-align: center;
|
|
||||||
color: #646a73;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
.no-border {
|
|
||||||
:deep(.el-input__wrapper) {
|
|
||||||
background: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-bottom: 1px solid #dcdfe6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input {
|
|
||||||
height: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-captcha {
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
:deep(.el-input__wrapper) {
|
|
||||||
background: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-bottom: 1px solid #dcdfe6;
|
|
||||||
}
|
|
||||||
.el-input {
|
|
||||||
width: 50%;
|
|
||||||
height: 44px;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
width: 45%;
|
|
||||||
height: 44px;
|
|
||||||
margin-left: 5%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-msg {
|
|
||||||
margin-top: 10px;
|
|
||||||
padding: 0 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-image {
|
|
||||||
width: 480px;
|
|
||||||
height: 480px;
|
|
||||||
@media only screen and (max-width: 1280px) {
|
|
||||||
height: 380px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.forget-password {
|
|
||||||
margin-top: 40px;
|
|
||||||
padding: 0 40px;
|
|
||||||
float: right;
|
|
||||||
@media only screen and (max-width: 1280px) {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-button {
|
|
||||||
width: 100%;
|
|
||||||
height: 45px;
|
|
||||||
margin-top: 10px;
|
|
||||||
background-color: #005eeb;
|
|
||||||
border-color: #005eeb;
|
|
||||||
color: #ffffff;
|
|
||||||
&:hover {
|
|
||||||
--el-button-hover-border-color: #005eeb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo {
|
|
||||||
text-align: center;
|
|
||||||
span {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form-header {
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
.title {
|
|
||||||
color: #646a73;
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.agree {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
line-height: 14px;
|
|
||||||
color: #005eeb;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(a) {
|
|
||||||
color: #005eeb;
|
|
||||||
&:hover {
|
|
||||||
color: #005eeb95;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-checkbox__input .el-checkbox__inner) {
|
|
||||||
background-color: #fff !important;
|
|
||||||
border-color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
|
||||||
background-color: #005eeb !important;
|
|
||||||
border-color: #005eeb !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-checkbox__input.is-checked .el-checkbox__inner::after) {
|
|
||||||
border-color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.agree-helper {
|
|
||||||
min-height: 20px;
|
|
||||||
margin-top: -20px;
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
:deep(.el-input__inner) {
|
|
||||||
color: #000 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cursor-pointer {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.el-dropdown:focus-visible {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.el-tooltip__trigger:focus-visible {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
:deep(.el-dropdown-menu__item:not(.is-disabled):hover) {
|
|
||||||
color: #005eeb !important;
|
|
||||||
background-color: #e5eefd !important;
|
|
||||||
}
|
|
||||||
:deep(.el-dropdown-menu__item:not(.is-disabled):focus) {
|
|
||||||
color: #005eeb !important;
|
|
||||||
background-color: #e5eefd !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-footer-btn {
|
|
||||||
.el-button--primary {
|
|
||||||
border-color: #005eeb !important;
|
|
||||||
background-color: #005eeb !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
-->
|
|
||||||
|
@ -19,23 +19,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div>
|
|
||||||
<div class="login-background" v-loading="loading">
|
|
||||||
<div class="login-wrapper">
|
|
||||||
<div :class="screenWidth > 1110 ? 'left inline-block' : ''">
|
|
||||||
<div class="login-title">
|
|
||||||
<span>{{ gStore.themeConfig.title || $t('setting.description') }}</span>
|
|
||||||
</div>
|
|
||||||
<img src="@/assets/images/1panel-login.png" alt="" v-if="screenWidth > 1110" />
|
|
||||||
</div>
|
|
||||||
<div :class="screenWidth > 1110 ? 'right inline-block' : ''">
|
|
||||||
<div class="login-container">
|
|
||||||
<LoginForm ref="loginRef"></LoginForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="login">
|
<script setup lang="ts" name="login">
|
||||||
@ -48,7 +31,7 @@ import { getXpackSettingForTheme } from '@/utils/xpack';
|
|||||||
|
|
||||||
const gStore = GlobalStore();
|
const gStore = GlobalStore();
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
const backgroundOpacity = ref(1);
|
const backgroundOpacity = ref(0.8);
|
||||||
const backgroundImage = ref(new URL('', import.meta.url).href);
|
const backgroundImage = ref(new URL('', import.meta.url).href);
|
||||||
const logoImage = ref(new URL('@/assets/images/1panel-login.png', import.meta.url).href);
|
const logoImage = ref(new URL('@/assets/images/1panel-login.png', import.meta.url).href);
|
||||||
|
|
||||||
@ -91,89 +74,3 @@ onMounted(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <style scoped lang="scss">
|
|
||||||
@mixin login-center {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-background {
|
|
||||||
height: 100vh;
|
|
||||||
background: url(@/assets/images/1panel-login-bg.png) no-repeat,
|
|
||||||
radial-gradient(153.25% 257.2% at 118.99% 181.67%, rgba(50, 132, 255, 0.2) 0%, rgba(82, 120, 255, 0) 100%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
radial-gradient(123.54% 204.83% at 25.87% 195.17%, rgba(111, 76, 253, 0.15) 0%, rgba(122, 76, 253, 0) 78.85%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
linear-gradient(0deg, rgba(0, 94, 235, 0.03), rgba(0, 94, 235, 0.03)),
|
|
||||||
radial-gradient(109.58% 109.58% at 31.53% -36.58%, rgba(0, 94, 235, 0.3) 0%, rgba(0, 94, 235, 0) 100%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
rgba(0, 57, 142, 0.05);
|
|
||||||
|
|
||||||
.login-wrapper {
|
|
||||||
padding-top: 8%;
|
|
||||||
width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
// @media only screen and (max-width: 1440px) {
|
|
||||||
// width: 100%;
|
|
||||||
// padding-top: 6%;
|
|
||||||
// }
|
|
||||||
.left {
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: right;
|
|
||||||
width: 60%;
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
width: 100%;
|
|
||||||
@media only screen and (min-width: 1440px) {
|
|
||||||
width: 85%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.right {
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
text-align: right;
|
|
||||||
margin-right: 10%;
|
|
||||||
span:first-child {
|
|
||||||
color: $primary-color;
|
|
||||||
font-size: 40px;
|
|
||||||
font-family: pingFangSC-Regular;
|
|
||||||
font-weight: 600;
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
font-size: 35px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 1110px) {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
font-size: 35px;
|
|
||||||
text-align: center;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.login-container {
|
|
||||||
margin-top: 40px;
|
|
||||||
padding: 40px 0;
|
|
||||||
width: 390px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: rgba(255, 255, 255, 0.55);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 2px 4px 22px rgba(0, 94, 235, 0.2);
|
|
||||||
@media only screen and (max-width: 1440px) {
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 1110px) {
|
|
||||||
margin: 60px auto 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style> -->
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user