完善私钥验证
This commit is contained in:
@ -1,9 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
"next-terminal/pkg/model"
|
"next-terminal/pkg/model"
|
||||||
"next-terminal/pkg/utils"
|
"next-terminal/pkg/utils"
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -51,6 +51,21 @@ func AssetUpdateEndpoint(c echo.Context) error {
|
|||||||
if err := c.Bind(&item); err != nil {
|
if err := c.Bind(&item); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
switch item.AccountType {
|
||||||
|
case "credential":
|
||||||
|
item.Username = "-"
|
||||||
|
item.Password = "-"
|
||||||
|
item.PrivateKey = "-"
|
||||||
|
item.Passphrase = "-"
|
||||||
|
case "private-key":
|
||||||
|
item.Username = "-"
|
||||||
|
item.Password = "-"
|
||||||
|
item.CredentialId = "-"
|
||||||
|
case "custom":
|
||||||
|
item.PrivateKey = "-"
|
||||||
|
item.Passphrase = "-"
|
||||||
|
item.CredentialId = "-"
|
||||||
|
}
|
||||||
|
|
||||||
model.UpdateAssetById(&item, id)
|
model.UpdateAssetById(&item, id)
|
||||||
|
|
||||||
|
@ -129,6 +129,8 @@ func SessionCreateEndpoint(c echo.Context) error {
|
|||||||
AssetId: asset.ID,
|
AssetId: asset.ID,
|
||||||
Username: asset.Username,
|
Username: asset.Username,
|
||||||
Password: asset.Password,
|
Password: asset.Password,
|
||||||
|
PrivateKey: asset.PrivateKey,
|
||||||
|
Passphrase: asset.Passphrase,
|
||||||
Protocol: asset.Protocol,
|
Protocol: asset.Protocol,
|
||||||
IP: asset.IP,
|
IP: asset.IP,
|
||||||
Port: asset.Port,
|
Port: asset.Port,
|
||||||
|
@ -2,15 +2,14 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"next-terminal/pkg/model"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"next-terminal/pkg/model"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -57,32 +56,7 @@ func SSHEndpoint(c echo.Context) error {
|
|||||||
width, _ := strconv.Atoi(c.QueryParam("width"))
|
width, _ := strconv.Atoi(c.QueryParam("width"))
|
||||||
height, _ := strconv.Atoi(c.QueryParam("height"))
|
height, _ := strconv.Atoi(c.QueryParam("height"))
|
||||||
|
|
||||||
asset, err := model.FindAssetById(assetId)
|
sshClient, err := CreateSshClient(assetId)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if asset.AccountType == "credential" {
|
|
||||||
credential, err := model.FindCredentialById(asset.CredentialId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
asset.Username = credential.Username
|
|
||||||
asset.Password = credential.Password
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
Timeout: 1 * time.Second,
|
|
||||||
User: asset.Username,
|
|
||||||
Auth: []ssh.AuthMethod{ssh.Password(asset.Password)},
|
|
||||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%d", asset.IP, asset.Port)
|
|
||||||
|
|
||||||
sshClient, err := ssh.Dial("tcp", addr, config)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -143,6 +117,55 @@ func SSHEndpoint(c echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateSshClient(assetId string) (*ssh.Client, error) {
|
||||||
|
asset, err := model.FindAssetById(assetId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var authMethod ssh.AuthMethod
|
||||||
|
if asset.AccountType == "credential" {
|
||||||
|
credential, err := model.FindCredentialById(asset.CredentialId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
asset.Username = credential.Username
|
||||||
|
asset.Password = credential.Password
|
||||||
|
authMethod = ssh.Password(asset.Password)
|
||||||
|
} else if asset.AccountType == "private-key" {
|
||||||
|
var key ssh.Signer
|
||||||
|
if len(asset.Passphrase) > 0 {
|
||||||
|
key, err = ssh.ParsePrivateKeyWithPassphrase([]byte(asset.PrivateKey), []byte(asset.Passphrase))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
key, err = ssh.ParsePrivateKey([]byte(asset.PrivateKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
authMethod = ssh.PublicKeys(key)
|
||||||
|
} else {
|
||||||
|
authMethod = ssh.Password(asset.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &ssh.ClientConfig{
|
||||||
|
Timeout: 1 * time.Second,
|
||||||
|
User: asset.Username,
|
||||||
|
Auth: []ssh.AuthMethod{authMethod},
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := fmt.Sprintf("%s:%d", asset.IP, asset.Port)
|
||||||
|
|
||||||
|
sshClient, err := ssh.Dial("tcp", addr, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sshClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
func WriteMessage(ws *websocket.Conn, message string) {
|
func WriteMessage(ws *websocket.Conn, message string) {
|
||||||
WriteByteMessage(ws, []byte(message))
|
WriteByteMessage(ws, []byte(message))
|
||||||
}
|
}
|
||||||
@ -154,19 +177,8 @@ func WriteByteMessage(ws *websocket.Conn, p []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateSftpClient(username, password, ip string, port int) (sftpClient *sftp.Client, err error) {
|
func CreateSftpClient(assetId string) (sftpClient *sftp.Client, err error) {
|
||||||
clientConfig := &ssh.ClientConfig{
|
sshClient, err := CreateSshClient(assetId)
|
||||||
Timeout: 1 * time.Second,
|
|
||||||
User: username,
|
|
||||||
Auth: []ssh.AuthMethod{ssh.Password(password)},
|
|
||||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%d", ip, port)
|
|
||||||
|
|
||||||
sshClient, err := ssh.Dial("tcp", addr, clientConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,15 @@ func TunEndpoint(c echo.Context) error {
|
|||||||
configuration.SetParameter("enable-sftp", "")
|
configuration.SetParameter("enable-sftp", "")
|
||||||
break
|
break
|
||||||
case "ssh":
|
case "ssh":
|
||||||
|
if session.PrivateKey == "-" {
|
||||||
configuration.SetParameter("username", session.Username)
|
configuration.SetParameter("username", session.Username)
|
||||||
configuration.SetParameter("password", session.Password)
|
configuration.SetParameter("password", session.Password)
|
||||||
|
} else {
|
||||||
|
configuration.SetParameter("private-key", session.PrivateKey)
|
||||||
|
configuration.SetParameter("passphrase", session.Passphrase)
|
||||||
|
}
|
||||||
|
|
||||||
sftpClient, err = CreateSftpClient(session.Username, session.Password, session.IP, session.Port)
|
sftpClient, err = CreateSftpClient(session.AssetId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ type Session struct {
|
|||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Recording string `json:"recording"`
|
Recording string `json:"recording"`
|
||||||
|
PrivateKey string `json:"privateKey"`
|
||||||
|
Passphrase string `json:"passphrase"`
|
||||||
ConnectedTime utils.JsonTime `json:"connectedTime"`
|
ConnectedTime utils.JsonTime `json:"connectedTime"`
|
||||||
DisconnectedTime utils.JsonTime `json:"disconnectedTime"`
|
DisconnectedTime utils.JsonTime `json:"disconnectedTime"`
|
||||||
}
|
}
|
||||||
|
69
web/public/bg.svg
Normal file
69
web/public/bg.svg
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="1361px" height="609px" viewBox="0 0 1361 609" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group 21</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Ant-Design-Pro-3.0" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="账户密码登录-校验" transform="translate(-79.000000, -82.000000)">
|
||||||
|
<g id="Group-21" transform="translate(77.000000, 73.000000)">
|
||||||
|
<g id="Group-18" opacity="0.8" transform="translate(74.901416, 569.699158) rotate(-7.000000) translate(-74.901416, -569.699158) translate(4.901416, 525.199158)">
|
||||||
|
<ellipse id="Oval-11" fill="#CFDAE6" opacity="0.25" cx="63.5748792" cy="32.468367" rx="21.7830479" ry="21.766008"></ellipse>
|
||||||
|
<ellipse id="Oval-3" fill="#CFDAE6" opacity="0.599999964" cx="5.98746479" cy="13.8668601" rx="5.2173913" ry="5.21330997"></ellipse>
|
||||||
|
<path d="M38.1354514,88.3520215 C43.8984227,88.3520215 48.570234,83.6838647 48.570234,77.9254015 C48.570234,72.1669383 43.8984227,67.4987816 38.1354514,67.4987816 C32.3724801,67.4987816 27.7006688,72.1669383 27.7006688,77.9254015 C27.7006688,83.6838647 32.3724801,88.3520215 38.1354514,88.3520215 Z" id="Oval-3-Copy" fill="#CFDAE6" opacity="0.45"></path>
|
||||||
|
<path d="M64.2775582,33.1704963 L119.185836,16.5654915" id="Path-12" stroke="#CFDAE6" stroke-width="1.73913043" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
<path d="M42.1431708,26.5002681 L7.71190162,14.5640702" id="Path-16" stroke="#E0B4B7" stroke-width="0.702678964" opacity="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
|
||||||
|
<path d="M63.9262187,33.521561 L43.6721326,69.3250951" id="Path-15" stroke="#BACAD9" stroke-width="0.702678964" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
|
||||||
|
<g id="Group-17" transform="translate(126.850922, 13.543654) rotate(30.000000) translate(-126.850922, -13.543654) translate(117.285705, 4.381889)" fill="#CFDAE6">
|
||||||
|
<ellipse id="Oval-4" opacity="0.45" cx="9.13482653" cy="9.12768076" rx="9.13482653" ry="9.12768076"></ellipse>
|
||||||
|
<path d="M18.2696531,18.2553615 C18.2696531,13.2142826 14.1798519,9.12768076 9.13482653,9.12768076 C4.08980114,9.12768076 0,13.2142826 0,18.2553615 L18.2696531,18.2553615 Z" id="Oval-4" transform="translate(9.134827, 13.691521) scale(-1, -1) translate(-9.134827, -13.691521) "></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-14" transform="translate(216.294700, 123.725600) rotate(-5.000000) translate(-216.294700, -123.725600) translate(106.294700, 35.225600)">
|
||||||
|
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.25" cx="29.1176471" cy="29.1402439" rx="29.1176471" ry="29.1402439"></ellipse>
|
||||||
|
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.3" cx="29.1176471" cy="29.1402439" rx="21.5686275" ry="21.5853659"></ellipse>
|
||||||
|
<ellipse id="Oval-2-Copy" stroke="#CFDAE6" opacity="0.4" cx="179.019608" cy="138.146341" rx="23.7254902" ry="23.7439024"></ellipse>
|
||||||
|
<ellipse id="Oval-2" fill="#BACAD9" opacity="0.5" cx="29.1176471" cy="29.1402439" rx="10.7843137" ry="10.7926829"></ellipse>
|
||||||
|
<path d="M29.1176471,39.9329268 L29.1176471,18.347561 C23.1616351,18.347561 18.3333333,23.1796097 18.3333333,29.1402439 C18.3333333,35.1008781 23.1616351,39.9329268 29.1176471,39.9329268 Z" id="Oval-2" fill="#BACAD9"></path>
|
||||||
|
<g id="Group-9" opacity="0.45" transform="translate(172.000000, 131.000000)" fill="#E6A1A6">
|
||||||
|
<ellipse id="Oval-2-Copy-2" cx="7.01960784" cy="7.14634146" rx="6.47058824" ry="6.47560976"></ellipse>
|
||||||
|
<path d="M0.549019608,13.6219512 C4.12262681,13.6219512 7.01960784,10.722722 7.01960784,7.14634146 C7.01960784,3.56996095 4.12262681,0.670731707 0.549019608,0.670731707 L0.549019608,13.6219512 Z" id="Oval-2-Copy-2" transform="translate(3.784314, 7.146341) scale(-1, 1) translate(-3.784314, -7.146341) "></path>
|
||||||
|
</g>
|
||||||
|
<ellipse id="Oval-10" fill="#CFDAE6" cx="218.382353" cy="138.685976" rx="1.61764706" ry="1.61890244"></ellipse>
|
||||||
|
<ellipse id="Oval-10-Copy-2" fill="#E0B4B7" opacity="0.35" cx="179.558824" cy="175.381098" rx="1.61764706" ry="1.61890244"></ellipse>
|
||||||
|
<ellipse id="Oval-10-Copy" fill="#E0B4B7" opacity="0.35" cx="180.098039" cy="102.530488" rx="2.15686275" ry="2.15853659"></ellipse>
|
||||||
|
<path d="M28.9985381,29.9671598 L171.151018,132.876024" id="Path-11" stroke="#CFDAE6" opacity="0.8"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group-10" opacity="0.799999952" transform="translate(1054.100635, 36.659317) rotate(-11.000000) translate(-1054.100635, -36.659317) translate(1026.600635, 4.659317)">
|
||||||
|
<ellipse id="Oval-7" stroke="#CFDAE6" stroke-width="0.941176471" cx="43.8135593" cy="32" rx="11.1864407" ry="11.2941176"></ellipse>
|
||||||
|
<g id="Group-12" transform="translate(34.596774, 23.111111)" fill="#BACAD9">
|
||||||
|
<ellipse id="Oval-7" opacity="0.45" cx="9.18534718" cy="8.88888889" rx="8.47457627" ry="8.55614973"></ellipse>
|
||||||
|
<path d="M9.18534718,17.4450386 C13.8657264,17.4450386 17.6599235,13.6143199 17.6599235,8.88888889 C17.6599235,4.16345787 13.8657264,0.332739156 9.18534718,0.332739156 L9.18534718,17.4450386 Z" id="Oval-7"></path>
|
||||||
|
</g>
|
||||||
|
<path d="M34.6597385,24.809694 L5.71666084,4.76878945" id="Path-2" stroke="#CFDAE6" stroke-width="0.941176471"></path>
|
||||||
|
<ellipse id="Oval" stroke="#CFDAE6" stroke-width="0.941176471" cx="3.26271186" cy="3.29411765" rx="3.26271186" ry="3.29411765"></ellipse>
|
||||||
|
<ellipse id="Oval-Copy" fill="#F7E1AD" cx="2.79661017" cy="61.1764706" rx="2.79661017" ry="2.82352941"></ellipse>
|
||||||
|
<path d="M34.6312443,39.2922712 L5.06366663,59.785082" id="Path-10" stroke="#CFDAE6" stroke-width="0.941176471"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group-19" opacity="0.33" transform="translate(1282.537219, 446.502867) rotate(-10.000000) translate(-1282.537219, -446.502867) translate(1142.537219, 327.502867)">
|
||||||
|
<g id="Group-17" transform="translate(141.333539, 104.502742) rotate(275.000000) translate(-141.333539, -104.502742) translate(129.333539, 92.502742)" fill="#BACAD9">
|
||||||
|
<circle id="Oval-4" opacity="0.45" cx="11.6666667" cy="11.6666667" r="11.6666667"></circle>
|
||||||
|
<path d="M23.3333333,23.3333333 C23.3333333,16.8900113 18.1099887,11.6666667 11.6666667,11.6666667 C5.22334459,11.6666667 0,16.8900113 0,23.3333333 L23.3333333,23.3333333 Z" id="Oval-4" transform="translate(11.666667, 17.500000) scale(-1, -1) translate(-11.666667, -17.500000) "></path>
|
||||||
|
</g>
|
||||||
|
<circle id="Oval-5-Copy-6" fill="#CFDAE6" cx="201.833333" cy="87.5" r="5.83333333"></circle>
|
||||||
|
<path d="M143.5,88.8126685 L155.070501,17.6038544" id="Path-17" stroke="#BACAD9" stroke-width="1.16666667"></path>
|
||||||
|
<path d="M17.5,37.3333333 L127.466252,97.6449735" id="Path-18" stroke="#BACAD9" stroke-width="1.16666667"></path>
|
||||||
|
<polyline id="Path-19" stroke="#CFDAE6" stroke-width="1.16666667" points="143.902597 120.302281 174.935455 231.571342 38.5 147.510847 126.366941 110.833333"></polyline>
|
||||||
|
<path d="M159.833333,99.7453842 L195.416667,89.25" id="Path-20" stroke="#E0B4B7" stroke-width="1.16666667" opacity="0.6"></path>
|
||||||
|
<path d="M205.333333,82.1372105 L238.719406,36.1666667" id="Path-24" stroke="#BACAD9" stroke-width="1.16666667"></path>
|
||||||
|
<path d="M266.723424,132.231988 L207.083333,90.4166667" id="Path-25" stroke="#CFDAE6" stroke-width="1.16666667"></path>
|
||||||
|
<circle id="Oval-5" fill="#C1D1E0" cx="156.916667" cy="8.75" r="8.75"></circle>
|
||||||
|
<circle id="Oval-5-Copy-3" fill="#C1D1E0" cx="39.0833333" cy="148.75" r="5.25"></circle>
|
||||||
|
<circle id="Oval-5-Copy-2" fill-opacity="0.6" fill="#D1DEED" cx="8.75" cy="33.25" r="8.75"></circle>
|
||||||
|
<circle id="Oval-5-Copy-4" fill-opacity="0.6" fill="#D1DEED" cx="243.833333" cy="30.3333333" r="5.83333333"></circle>
|
||||||
|
<circle id="Oval-5-Copy-5" fill="#E0B4B7" cx="175.583333" cy="232.75" r="5.25"></circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 8.7 KiB |
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<title>Next Terminal</title>
|
<title>Next Terminal</title>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: darkgrey">
|
<body style="background-color: #8c8c8c">
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<!--
|
<!--
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,12 +1,13 @@
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Button, Card, Checkbox, Form, Input} from "antd";
|
import {Button, Card, Checkbox, Form, Input, Typography} from "antd";
|
||||||
import './Login.css'
|
import './Login.css'
|
||||||
import request from "../common/request";
|
import request from "../common/request";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import {
|
import {LockOutlined, UserOutlined} from '@ant-design/icons';
|
||||||
UserOutlined, LockOutlined
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
|
const {Title} = Typography;
|
||||||
|
|
||||||
class LoginForm extends Component {
|
class LoginForm extends Component {
|
||||||
|
|
||||||
@ -48,9 +49,12 @@ class LoginForm extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className='login-card' title="登录">
|
<div className='login-bg' style={{width: window.innerWidth, height: window.innerHeight, backgroundColor: '#F0F2F5'}}>
|
||||||
|
<Card className='login-card' title={null}>
|
||||||
|
<div style={{textAlign: "center", margin: '15px auto 30px auto', color: '#1890ff'}}>
|
||||||
|
<Title level={1}>Next Terminal</Title>
|
||||||
|
</div>
|
||||||
<Form onFinish={this.handleSubmit} className="login-form">
|
<Form onFinish={this.handleSubmit} className="login-form">
|
||||||
<Form.Item name='username' rules={[{required: true, message: '请输入登录账号!'}]}>
|
<Form.Item name='username' rules={[{required: true, message: '请输入登录账号!'}]}>
|
||||||
<Input prefix={<UserOutlined/>} placeholder="登录账号"/>
|
<Input prefix={<UserOutlined/>} placeholder="登录账号"/>
|
||||||
@ -71,6 +75,8 @@ class LoginForm extends Component {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Card>
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -766,12 +766,12 @@ class Access extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<div className="container" style={{
|
<div className="container" style={{
|
||||||
overflow: this.state.containerOverflow,
|
overflow: this.state.containerOverflow,
|
||||||
width: this.state.containerWidth,
|
width: this.state.containerWidth,
|
||||||
height: this.state.containerHeight
|
height: this.state.containerHeight
|
||||||
}}>
|
}}>
|
||||||
|
|
||||||
<div id="display"/>
|
<div id="display"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -17,6 +17,14 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
|
|||||||
setAccountType(model.accountType);
|
setAccountType(model.accountType);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (let key in model) {
|
||||||
|
if (model.hasOwnProperty(key)) {
|
||||||
|
if (model[key] === '-') {
|
||||||
|
model[key] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
labelCol: {span: 6},
|
labelCol: {span: 6},
|
||||||
wrapperCol: {span: 14},
|
wrapperCol: {span: 14},
|
||||||
@ -54,7 +62,7 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
|
|||||||
<Modal
|
<Modal
|
||||||
title={title}
|
title={title}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
maskClosable={true}
|
maskClosable={false}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
form
|
form
|
||||||
.validateFields()
|
.validateFields()
|
||||||
@ -62,7 +70,8 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
|
|||||||
form.resetFields();
|
form.resetFields();
|
||||||
handleOk(values);
|
handleOk(values);
|
||||||
})
|
})
|
||||||
.catch(info => {});
|
.catch(info => {
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
confirmLoading={confirmLoading}
|
confirmLoading={confirmLoading}
|
||||||
@ -103,7 +112,7 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
|
|||||||
}}>
|
}}>
|
||||||
<Option value="custom">自定义</Option>
|
<Option value="custom">自定义</Option>
|
||||||
<Option value="credential">授权凭证</Option>
|
<Option value="credential">授权凭证</Option>
|
||||||
<Option value="secret-key">密钥</Option>
|
<Option value="private-key">私钥</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
@ -143,10 +152,17 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
accountType === 'secret-key' ?
|
accountType === 'private-key' ?
|
||||||
<Form.Item label="私钥" name='passphrase' rules={[{required: true, message: '请输入私钥'}]}>
|
<>
|
||||||
|
<Form.Item label="私钥" name='privateKey' rules={[{required: true, message: '请输入私钥'}]}>
|
||||||
<TextArea rows={4}/>
|
<TextArea rows={4}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label="私钥密码" name='passphrase'>
|
||||||
|
<TextArea rows={1}/>
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
|
|
||||||
|
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -481,12 +481,14 @@ class OfflineSession extends Component {
|
|||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
title="会话回放"
|
title="会话回放"
|
||||||
|
centered
|
||||||
visible={this.state.playbackVisible}
|
visible={this.state.playbackVisible}
|
||||||
onCancel={this.hidePlayback}
|
onCancel={this.hidePlayback}
|
||||||
|
|
||||||
width={window.innerWidth * 0.8}
|
width={window.innerWidth * 0.8}
|
||||||
footer={null}
|
footer={null}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
|
maskClosable={false}
|
||||||
>
|
>
|
||||||
<Playback sessionId={this.state.playbackSessionId}/>
|
<Playback sessionId={this.state.playbackSessionId}/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -477,6 +477,7 @@ class OnlineSession extends Component {
|
|||||||
className='monitor'
|
className='monitor'
|
||||||
title={this.state.sessionTitle}
|
title={this.state.sessionTitle}
|
||||||
centered
|
centered
|
||||||
|
maskClosable={false}
|
||||||
visible={this.state.accessVisible}
|
visible={this.state.accessVisible}
|
||||||
footer={null}
|
footer={null}
|
||||||
width={window.innerWidth * 0.8}
|
width={window.innerWidth * 0.8}
|
||||||
|
Reference in New Issue
Block a user