forked from fanruan/design
Browse Source
Merge in DESIGN/design from ~XIQIU/design:feature/x to feature/x * commit '3d183c113b7941ca53511fe7ae7b206a5039a4c6': REPORT-64012 ssh与ssl 实现feature/x
Xiqiu
3 years ago
7 changed files with 609 additions and 24 deletions
@ -0,0 +1,275 @@
|
||||
package com.fr.design.data.datapane.connect; |
||||
|
||||
import com.fr.data.impl.JDBCDatabaseConnection; |
||||
import com.fr.data.security.ssh.BaseSsh; |
||||
import com.fr.data.security.ssh.Ssh; |
||||
import com.fr.data.security.ssh.SshException; |
||||
import com.fr.data.security.ssh.SshType; |
||||
import com.fr.data.security.ssh.impl.KeyVerifySsh; |
||||
import com.fr.data.security.ssh.impl.NormalSsh; |
||||
import com.fr.data.security.ssl.SslUtils; |
||||
import com.fr.design.border.UITitledBorder; |
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.editor.editor.NotNegativeIntegerEditor; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icheckbox.UICheckBox; |
||||
import com.fr.design.gui.icombobox.UIComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.file.FILE; |
||||
import com.fr.file.FILEChooserPane; |
||||
import com.fr.file.filter.ChooseFileFilter; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
import com.fr.third.guava.collect.HashBiMap; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPasswordField; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
|
||||
import static com.fr.design.i18n.Toolkit.i18nText; |
||||
|
||||
/** |
||||
* @author xiqiu |
||||
* @date 2021/12/23 |
||||
* @description |
||||
*/ |
||||
public class SshPane extends BasicPane { |
||||
private static HashBiMap<String, SshType> typeMap; |
||||
|
||||
static { |
||||
typeMap = HashBiMap.create(); |
||||
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Password"), SshType.NORMAL); |
||||
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Ssh_Public_Key"), SshType.KEY); |
||||
} |
||||
|
||||
private UICheckBox usingSsh = new UICheckBox(i18nText("Fine-Design_Basic_Ssh_Using")); |
||||
private NotNegativeIntegerEditor port = new NotNegativeIntegerEditor(); |
||||
private UITextField ip = new UITextField(); |
||||
private UIComboBox type = new UIComboBox(); |
||||
private UITextField user = new UITextField(); |
||||
private JPasswordField password = new UIPasswordFieldWithFixedLength(20); |
||||
private JPasswordField secret = new UIPasswordFieldWithFixedLength(20); |
||||
private KeyFileUITextField keyPath = new KeyFileUITextField(); |
||||
private JPanel contextPane; |
||||
private Component[][] passwordComps; |
||||
private Component[][] keyComps; |
||||
private double p = TableLayout.PREFERRED; |
||||
private double f = TableLayout.FILL; |
||||
private JPanel jPanel; |
||||
private UIButton fileChooserButton = new UIButton("..."); |
||||
private double[] columnSize = new double[]{208, p}; |
||||
|
||||
public SshPane() { |
||||
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings"))); |
||||
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); |
||||
typeMap.keySet().forEach(key -> type.addItem(key)); |
||||
type.setSelectedItem(typeMap.inverse().get(SshType.KEY)); |
||||
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
keyPath.setColumns(18); |
||||
fileChooserButton.setPreferredSize(new Dimension(20, 20)); |
||||
type.setEditable(false); |
||||
type.setSelectedItem(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key")); |
||||
JPanel filePanel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||
filePanel.add(keyPath); |
||||
filePanel.add(fileChooserButton); |
||||
Component[] compIp = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Host") + ":", SwingConstants.RIGHT), ip}; |
||||
Component[] compPort = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Port") + ":", SwingConstants.RIGHT), port}; |
||||
Component[] compUserName = {new UILabel(Toolkit.i18nText("Fine-Design_Report_UserName") + ":", SwingConstants.RIGHT), user}; |
||||
Component[] compMethod = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Verify_Method") + ":", SwingConstants.RIGHT), type}; |
||||
Component[] compPassword = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Password") + ":", SwingConstants.RIGHT), password}; |
||||
Component[] compKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key") + ":", SwingConstants.RIGHT), filePanel}; |
||||
Component[] comSecret = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Secret") + ":", SwingConstants.RIGHT), secret}; |
||||
|
||||
passwordComps = new Component[][]{ |
||||
compIp, |
||||
compPort, |
||||
compUserName, |
||||
compMethod, |
||||
compPassword |
||||
}; |
||||
keyComps = new Component[][]{ |
||||
compIp, |
||||
compPort, |
||||
compUserName, |
||||
compMethod, |
||||
compKey, |
||||
comSecret |
||||
}; |
||||
usingSsh.setSelected(true); |
||||
contextPane = TableLayoutHelper.createGapTableLayoutPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, 11, 11); |
||||
jPanel.add(usingSsh, BorderLayout.NORTH); |
||||
jPanel.add(contextPane, BorderLayout.CENTER); |
||||
this.add(jPanel); |
||||
|
||||
usingSsh.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
changePane(); |
||||
} |
||||
}); |
||||
|
||||
type.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
changePaneForType(); |
||||
} |
||||
}); |
||||
fileChooserButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(SslUtils.KEY_FILE_EXTENSION)); |
||||
int type = fileChooser.showOpenDialog(SshPane.this); |
||||
if (type == FILEChooserPane.OK_OPTION) { |
||||
final FILE file = fileChooser.getSelectedFILE(); |
||||
if (file == null) { |
||||
keyPath.setText(StringUtils.EMPTY); |
||||
} else { |
||||
keyPath.setText(file.getPath()); |
||||
} |
||||
} |
||||
fileChooser.removeAllFilter(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
private void changePane() { |
||||
contextPane.setVisible(usingSsh.isSelected()); |
||||
} |
||||
|
||||
private void changePaneForType() { |
||||
contextPane.removeAll(); |
||||
switch (typeMap.get(type.getSelectedItem())) { |
||||
case NORMAL: |
||||
TableLayoutHelper.addComponent2ResultPane(passwordComps, new double[]{p, p, p, p, p}, columnSize, contextPane); |
||||
break; |
||||
case KEY: |
||||
TableLayoutHelper.addComponent2ResultPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, contextPane); |
||||
break; |
||||
default: |
||||
throw new SshException("un support ssh type"); |
||||
} |
||||
jPanel.revalidate(); |
||||
jPanel.repaint(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings"); |
||||
} |
||||
|
||||
|
||||
public void populate(JDBCDatabaseConnection jdbcDatabase) { |
||||
if (jdbcDatabase.getSsh() == null) { |
||||
jdbcDatabase.setSsh(new NormalSsh()); |
||||
} |
||||
Ssh ssh = jdbcDatabase.getSsh(); |
||||
switch (ssh.getSshType()) { |
||||
case KEY: |
||||
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType())); |
||||
KeyVerifySsh keyVerifySsh = (KeyVerifySsh) ssh; |
||||
keyPath.setText(keyVerifySsh.getPrivateKeyPath()); |
||||
secret.setText(keyVerifySsh.getSecret()); |
||||
password.setText(StringUtils.EMPTY); |
||||
setCommonConfig(keyVerifySsh); |
||||
break; |
||||
case NORMAL: |
||||
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType())); |
||||
NormalSsh normalSsh = (NormalSsh) ssh; |
||||
password.setText(normalSsh.getSecret()); |
||||
keyPath.setText(StringUtils.EMPTY); |
||||
secret.setText(StringUtils.EMPTY); |
||||
setCommonConfig(normalSsh); |
||||
break; |
||||
default: |
||||
throw new SshException("un support ssh type"); |
||||
} |
||||
usingSsh.setSelected(ssh.isUsingSsh()); |
||||
changePane(); |
||||
} |
||||
|
||||
private void setCommonConfig(BaseSsh baseSsh) { |
||||
ip.setText(baseSsh.getIp()); |
||||
port.setValue(baseSsh.getPort()); |
||||
user.setText(baseSsh.getUser()); |
||||
} |
||||
|
||||
public void update(JDBCDatabaseConnection jdbcDatabase) { |
||||
Ssh ssh; |
||||
switch (typeMap.get(type.getSelectedItem())) { |
||||
case NORMAL: |
||||
NormalSsh normalSsh = new NormalSsh(); |
||||
normalSsh.setSecret(new String(password.getPassword()).trim()); |
||||
getCommonConfig(normalSsh); |
||||
ssh = normalSsh; |
||||
break; |
||||
case KEY: |
||||
KeyVerifySsh keyVerifySsh = new KeyVerifySsh(); |
||||
keyVerifySsh.setPrivateKeyPath(keyPath.getText().trim()); |
||||
keyVerifySsh.setSecret(new String(secret.getPassword()).trim()); |
||||
getCommonConfig(keyVerifySsh); |
||||
ssh = keyVerifySsh; |
||||
break; |
||||
default: |
||||
throw new SshException("un support ssh type"); |
||||
} |
||||
jdbcDatabase.setSsh(ssh); |
||||
} |
||||
|
||||
private void getCommonConfig(BaseSsh baseSsh) { |
||||
baseSsh.setUsingSsh(usingSsh.isSelected()); |
||||
baseSsh.setIp(ip.getText().trim()); |
||||
baseSsh.setPort(port.getValue()); |
||||
baseSsh.setUser(user.getText().trim()); |
||||
} |
||||
|
||||
public static class KeyFileUITextField extends UITextField { |
||||
private static final String PREFIX = ProjectConstants.RESOURCES_NAME + "/"; |
||||
private static final String UPPER = ".."; |
||||
|
||||
public KeyFileUITextField() { |
||||
super(); |
||||
this.addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyReleased(KeyEvent e) { |
||||
String text = KeyFileUITextField.this.getText(); |
||||
if (text != null && text.contains(UPPER)) { |
||||
KeyFileUITextField.this.setText(text.replace(UPPER, ".")); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String getText() { |
||||
// 获取的时候,不为空,给他加上前缀就好了,否则还是空
|
||||
if (!StringUtils.isEmpty(super.getText())) { |
||||
return PREFIX + super.getText(); |
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
@Override |
||||
public void setText(String text) { |
||||
// 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀
|
||||
if (!StringUtils.isEmpty(text)) { |
||||
super.setText(text.replace(PREFIX, "")); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,170 @@
|
||||
package com.fr.design.data.datapane.connect; |
||||
|
||||
import com.fr.data.impl.JDBCDatabaseConnection; |
||||
import com.fr.data.security.ssl.Ssl; |
||||
import com.fr.data.security.ssl.SslException; |
||||
import com.fr.data.security.ssl.SslType; |
||||
import com.fr.data.security.ssl.SslUtils; |
||||
import com.fr.data.security.ssl.impl.NormalSsl; |
||||
import com.fr.design.border.UITitledBorder; |
||||
import com.fr.design.data.datapane.connect.SshPane.KeyFileUITextField; |
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icheckbox.UICheckBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.file.FILE; |
||||
import com.fr.file.FILEChooserPane; |
||||
import com.fr.file.filter.ChooseFileFilter; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
import static com.fr.design.i18n.Toolkit.i18nText; |
||||
|
||||
/** |
||||
* @author xiqiu |
||||
* @date 2022/1/4 |
||||
* @description |
||||
*/ |
||||
public class SslPane extends BasicPane { |
||||
UICheckBox usingSsl = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Using")); |
||||
private KeyFileUITextField keyPathCa = new KeyFileUITextField(); |
||||
private UIButton fileChooserButtonCa = new UIButton("..."); |
||||
private KeyFileUITextField keyPathClientCert = new KeyFileUITextField(); |
||||
private UIButton fileChooserButtonClientCert = new UIButton("..."); |
||||
private KeyFileUITextField keyPathClientKey = new KeyFileUITextField(); |
||||
private UIButton fileChooserButtonClientKey = new UIButton("..."); |
||||
private UICheckBox verifyCa = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Verify_Ca")); |
||||
private UITextField cipher = new UITextField(); |
||||
private JPanel jPanel; |
||||
private Component[][] usingComps; |
||||
private double p = TableLayout.PREFERRED; |
||||
private double f = TableLayout.FILL; |
||||
private JPanel contextPane; |
||||
private double[] columnSize = new double[]{208, p}; |
||||
|
||||
public SslPane() { |
||||
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings"))); |
||||
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); |
||||
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
Dimension dimension = new Dimension(20, 20); |
||||
int columns = 18; |
||||
keyPathCa.setColumns(columns); |
||||
fileChooserButtonCa.setPreferredSize(dimension); |
||||
keyPathClientCert.setColumns(columns); |
||||
fileChooserButtonClientCert.setPreferredSize(dimension); |
||||
fileChooserButtonClientKey.setPreferredSize(dimension); |
||||
keyPathClientKey.setColumns(columns); |
||||
JPanel filePanelCa = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||
filePanelCa.add(keyPathCa); |
||||
filePanelCa.add(fileChooserButtonCa); |
||||
Component[] compCa = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Ca") + ":", SwingConstants.RIGHT), filePanelCa}; |
||||
Component[] compVerifyCa = {null, verifyCa}; |
||||
JPanel filePanelClientCert = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||
filePanelClientCert.add(keyPathClientCert); |
||||
filePanelClientCert.add(fileChooserButtonClientCert); |
||||
Component[] compClientCert = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Cert") + ":", SwingConstants.RIGHT), filePanelClientCert}; |
||||
JPanel filePanelClientKey = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); |
||||
filePanelClientKey.add(keyPathClientKey); |
||||
filePanelClientKey.add(fileChooserButtonClientKey); |
||||
Component[] compClientKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Key") + ":", SwingConstants.RIGHT), filePanelClientKey}; |
||||
Component[] comCipher = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Cipher") + ":", SwingConstants.RIGHT), cipher}; |
||||
usingComps = new Component[][]{ |
||||
compCa, |
||||
compVerifyCa, |
||||
compClientCert, |
||||
compClientKey, |
||||
comCipher |
||||
}; |
||||
usingSsl.setSelected(true); |
||||
contextPane = TableLayoutHelper.createGapTableLayoutPane(usingComps, new double[]{p, p, p, p, p, p}, columnSize, 11, 11); |
||||
jPanel.add(usingSsl, BorderLayout.NORTH); |
||||
jPanel.add(contextPane, BorderLayout.CENTER); |
||||
this.add(jPanel); |
||||
usingSsl.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
changePane(); |
||||
} |
||||
}); |
||||
fileChooserButtonCa.addActionListener(new TextFieldActionListener(keyPathCa)); |
||||
fileChooserButtonClientCert.addActionListener(new TextFieldActionListener(keyPathClientCert)); |
||||
fileChooserButtonClientKey.addActionListener(new TextFieldActionListener(keyPathClientKey)); |
||||
} |
||||
|
||||
private void changePane() { |
||||
contextPane.setVisible(usingSsl.isSelected()); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings"); |
||||
} |
||||
|
||||
public void populate(JDBCDatabaseConnection jdbcDatabase) { |
||||
Ssl ssl = jdbcDatabase.getSsl(); |
||||
if (ssl == null) { |
||||
ssl = new NormalSsl(); |
||||
jdbcDatabase.setSsl(ssl); |
||||
} |
||||
if (ssl.getSslType() == SslType.NORMAL) { |
||||
NormalSsl normalSsl = (NormalSsl) ssl; |
||||
keyPathCa.setText(normalSsl.getCaCertificate()); |
||||
keyPathClientCert.setText(normalSsl.getClientCertificate()); |
||||
keyPathClientKey.setText(normalSsl.getClientPrivateKey()); |
||||
verifyCa.setSelected(normalSsl.isVerifyCa()); |
||||
cipher.setText(normalSsl.getCipher()); |
||||
} else { |
||||
throw new SslException("un support ssl type"); |
||||
} |
||||
usingSsl.setSelected(ssl.isUsingSsl()); |
||||
changePane(); |
||||
} |
||||
|
||||
public void update(JDBCDatabaseConnection jdbcDatabase) { |
||||
NormalSsl normalSsl = new NormalSsl(); |
||||
normalSsl.setCipher(cipher.getText().trim()); |
||||
normalSsl.setVerifyCa(verifyCa.isSelected()); |
||||
normalSsl.setCaCertificate(keyPathCa.getText().trim()); |
||||
normalSsl.setClientCertificate(keyPathClientCert.getText().trim()); |
||||
normalSsl.setClientPrivateKey(keyPathClientKey.getText().trim()); |
||||
normalSsl.setUsingSsl(usingSsl.isSelected()); |
||||
jdbcDatabase.setSsl(normalSsl); |
||||
} |
||||
|
||||
private class TextFieldActionListener implements ActionListener { |
||||
private UITextField textField; |
||||
|
||||
public TextFieldActionListener(UITextField textField) { |
||||
this.textField = textField; |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(SslUtils.KEY_FILE_EXTENSION)); |
||||
int type = fileChooser.showOpenDialog(SslPane.this); |
||||
if (type == FILEChooserPane.OK_OPTION) { |
||||
final FILE file = fileChooser.getSelectedFILE(); |
||||
if (file == null) { |
||||
textField.setText(StringUtils.EMPTY); |
||||
} else { |
||||
textField.setText(file.getPath()); |
||||
} |
||||
} |
||||
fileChooser.removeAllFilter(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,28 @@
|
||||
package com.fr.design.editor.editor; |
||||
|
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
|
||||
/** |
||||
* @author xiqiu |
||||
* @date 2022/1/10 |
||||
* @description 一个简单的非负整数框 |
||||
*/ |
||||
public class NotNegativeIntegerEditor extends IntegerEditor { |
||||
private static final String NEG = "-"; |
||||
|
||||
public NotNegativeIntegerEditor() { |
||||
super(); |
||||
this.numberField.addKeyListener(new KeyAdapter() { |
||||
|
||||
@Override |
||||
public void keyReleased(KeyEvent evt) { |
||||
char keyChar = evt.getKeyChar(); |
||||
if (NEG.equals(keyChar + "")) { |
||||
numberField.setText(numberField.getTextValue().replace(NEG, "")); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue