所有源代码都在资源中有上传,这里我们主要构建了两个项目,第一个是一个简单的web登陆页面。
一、对登陆密码加密:
搭建过程不赘述
1、数据库中执行:update account set password=MD5(password)
一开始我是这么做的:update account set password=MD5('password'),注意别傻
这样一来就将数据库中的密码用MD5摘要处理了,注意页面中相应修改代码。为加大破译难度,我们通常采用了是下面的方法,用其他信息(如邮箱)当做盐,加盐处理。
2.安全升级-加盐处理:update account set password = sha(concat(email,password))
注意相应代码修改,如校验部分:
if(p.equals(DigestUtils.shaHex(email+password)){ }
二、实例:IM应用开发安全:
安全升级-隐藏数据
安全升级-加密数据
这里我们基于UDPSocket搭建了一个聊天系统。将网络中传递的数据隐藏(Base64并)加密
socket.send(Security.encrypt(message.getBytes(CHARSET)));
byte[] data = Security.decrypt(socket.receive());
String message = new String(data,CHARSET);
三、IM应用开发:
介于自己对应用搭建部分不熟,下面分析下这部分代码:
MainFrame 类:
用mainFrame对象开启一个线程:
public static void main(String[] args) throws UnknownHostException, SocketException{
MainFrame mainFrame = new MainFrame();
Thread t = new Thread(mainFrame);
t.start();
}
public void run() {
while(true){
try {
receive();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
线程内循环接收数据。
当接收到数据:
public void receive() throws UnsupportedEncodingException, IOException{
byte[] data = Security.decrypt(socket.receive());
String message = new String(data,CHARSET);
StringBuilder sb = new StringBuilder();
sb.append(receiveArea.getText());
sb.append(message);
receiveArea.setText(sb.toString());
}
解密,刷新接收框,将新收到的数据追加到最后。
怎么追加到最后的?
先把已有的数据拿到,放到StringBuilder,再追加
MainFrame类里有这几个对象:
private static final String CHARSET="UTF-8";
private UDPSocket socket;
private InitDialog initDialog;
public static final int DEFAULT_WIDTH=500;
public static final int DEFAULT_HEIGHT=400;
private JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
private JTextArea sendTextArea = new JTextArea();
private JTextArea receiveArea = new JTextArea();
private JPanel buttonPanel = new JPanel();
操作部分:UDP套接口,initDialog
图形部分:一个水平分割的pane,输入输出区,按钮区
初始化时:
public MainFrame() throws UnknownHostException, SocketException{
this.initDialog = new InitDialog(this);
if(initDialog.isCancelled()){
System.exit(0);
}else{
initSocket();
initGUI();
}
}
InitDialog.java:
public class InitDialog extends JDialog {
private static final int DEFAULT_WIDTH=200;
private static final int DEFAULT_HEIGHT=210;
private int receivePort;
private int sendPort;
private String username;
private String remoteHost;
private String localHost;
private boolean cancelled =true;
public int getReceivePort() {
return receivePort;
}
public void setReceivePort(int receivePort) {
this.receivePort = receivePort;
}
public int getSendPort() {
return sendPort;
}
public void setSendPort(int sendPort) {
this.sendPort = sendPort;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRemoteHost() {
return remoteHost;
}
public void setRemoteHost(String remoteHost) {
this.remoteHost = remoteHost;
}
public String getLocalHost() {
return localHost;
}
public void setLocalHost(String localHost) {
this.localHost = localHost;
}
public boolean isCancelled() {
return cancelled;
}
public InitDialog(Frame owner) throws UnknownHostException{
super(owner,"初始化对话窗",true);
String local;
local=InetAddress.getLocalHost().getHostAddress();
final JTextField remoteHostField = new JTextField(local,10);
final JTextField localHostField = new JTextField(local,10);
final JTextField receivePortField = new JTextField("8001",10);
final JTextField sendPortField = new JTextField("8002",10);
final JTextField usernameField = new JTextField("zlex",10);
JPanel inputPanel = new JPanel();
inputPanel.setMinimumSize(new Dimension(80,120));
inputPanel.setBorder(BorderFactory.createEtchedBorder());
inputPanel.add(new JLabel("目标主机: "));
inputPanel.add(remoteHostField);
inputPanel.add(new JLabel("本地主机: "));
inputPanel.add(localHostField);
inputPanel.add(new JLabel("接收端口: "));
inputPanel.add(receivePortField);
inputPanel.add(new JLabel("发送端口: "));
inputPanel.add(sendPortField);
inputPanel.add(new JLabel("用户昵称: "));
inputPanel.add(usernameField);
JButton okButton = new JButton("确定");
okButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
remoteHost = remoteHostField.getText();
localHost = localHostField.getText();
receivePort = Integer.parseInt(receivePortField.getText());
sendPort = Integer.parseInt(sendPortField.getText());
username = usernameField.getText();
cancelled= false;
InitDialog.this.dispose();
}
});
JButton cancelButton = new JButton("取消");
cancelButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
InitDialog.this.dispose();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(okButton);
buttonPanel.add(cancelButton);
getContentPane().add(inputPanel,BorderLayout.CENTER);
getContentPane().add(buttonPanel,BorderLayout.SOUTH);
setMinimumSize(new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT));
setResizable(true);
setLocationRelativeTo(null);
setVisible(true);
}
}
UDPSocket.java:
public class UDPSocket {
private byte[] buffer = new byte[1024];
private DatagramSocket receiveSocket;
private DatagramSocket sendSocket;
private String remoteHost;
private int sendPort;
public UDPSocket(String localHost,String remoteHost,int receivePort,int sendPort) throws SocketException{
this.remoteHost=remoteHost;
this.sendPort=sendPort;
this.receiveSocket=new DatagramSocket(new InetSocketAddress(localHost,receivePort));
this.sendSocket=new DatagramSocket();
}
public byte[] receive() throws IOException{
DatagramPacket dp = new DatagramPacket(buffer,buffer.length);
receiveSocket.receive(dp);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(dp.getData(),0,dp.getLength());
byte[] data = baos.toByteArray();
baos.flush();
baos.close();
return data;
}
public void send(byte[] data) throws IOException{
DatagramPacket dp = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(remoteHost),sendPort);
dp.setData(data);
sendSocket.send(dp);
}
public void close(){
try{
if(receiveSocket.isConnected()){
receiveSocket.disconnect();
receiveSocket.close();
}
if(sendSocket.isConnected()){
sendSocket.disconnect();
sendSocket.close();
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
public UDPSocket(String localHost,String remoteHost,int receivePort,int sendPort) throws SocketException{
this.remoteHost=remoteHost;
this.sendPort=sendPort;
this.receiveSocket=new DatagramSocket(new InetSocketAddress(localHost,receivePort));
this.sendSocket=new DatagramSocket();
}
可以把套接口视作应用层与传输层之间,接收是往上传到应用层,发送往下到传输层。
应用层是端口到端口传输的,接收套接口应有本地信息,往哪个端口传。
public byte[] receive() throws IOException{
DatagramPacket dp = new DatagramPacket(buffer,buffer.length);
receiveSocket.receive(dp);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(dp.getData(),0,dp.getLength());
byte[] data = baos.toByteArray();
baos.flush();
baos.close();
return data;
}
真正接收的时候,拿到数据包后,转成输出流,输出到计算机终端
可以形象理解:输入输出流针对应用层而言的,输出流流向计算机屏幕,输入流从键盘流进应用。
真正发送的时候,
public void send(byte[] data) throws IOException{
DatagramPacket dp = new DatagramPacket(buffer,buffer.length,InetAddress.getByName(remoteHost),sendPort);
dp.setData(data);
sendSocket.send(dp);
}
最细的也无非就是DatagramSocket 类的receiveSocket.receive()和sendSocket.send()操作了。两者操作的参数都是DatagramPacket
最后,MainFrame完整代码:
public class MainFrame extends JFrame implements Runnable{
private static final String CHARSET="UTF-8";
private UDPSocket socket;
private InitDialog initDialog;
public static final int DEFAULT_WIDTH=500;
public static final int DEFAULT_HEIGHT=400;
private JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
private JTextArea sendTextArea = new JTextArea();
private JTextArea receiveArea = new JTextArea();
private JPanel buttonPanel = new JPanel();
public MainFrame() throws UnknownHostException, SocketException{
this.initDialog = new InitDialog(this);
if(initDialog.isCancelled()){
System.exit(0);
}else{
initSocket();
initGUI();
}
}
private void initGUI() {
setTitle("From: "+initDialog.getLocalHost()+" To:"+initDialog.getRemoteHost());
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setMinimumSize(new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT));
this.getContentPane().add(splitPane,BorderLayout.CENTER);
this.getContentPane().add(buttonPanel,BorderLayout.SOUTH);
this.initReceivePanel();
this.initSendPanel();
this.initButtonPannel();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
}
private void initSendPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBorder(BorderFactory.createEtchedBorder());
JLabel label = new JLabel();
label.setText("待发送的消息:");
panel.add(label,BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setWheelScrollingEnabled(true);
DefaultCaret caret = (DefaultCaret)receiveArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
sendTextArea.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent event){
if((event.getKeyCode()==KeyEvent.VK_ENTER)&&event.isControlDown()){
try {
send(sendTextArea.getText());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
scrollPane.getViewport().add(sendTextArea);
panel.add(scrollPane,BorderLayout.CENTER);
splitPane.add(panel);
}
private void initReceivePanel() {
receiveArea.setEditable(true);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBorder(BorderFactory.createEtchedBorder());
JLabel label = new JLabel();
label.setText("接收到的消息");
panel.add(label,BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport().add(receiveArea);
DefaultCaret caret = (DefaultCaret)receiveArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
panel.add(scrollPane,BorderLayout.CENTER);
panel.setMinimumSize(new Dimension(0,DEFAULT_WIDTH/3));
splitPane.add(panel);
}
private void initButtonPannel() {
JButton sendButton = new JButton("发送(s)");
sendButton.setMnemonic(KeyEvent.VK_S);
sendButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
try {
send(sendTextArea.getText());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
JButton exitButton = new JButton("关闭(X)");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
socket.close();System.exit(0);
}
});
}
public void send(String message) throws UnsupportedEncodingException, IOException{
if(message.isEmpty()){
return;
}
else{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
StringBuilder sendMessage = new StringBuilder();
sendMessage.append(df.format(new Date()));
sendMessage.append("("+initDialog.getUsername()+")");
sendMessage.append("\r\n");
sendMessage.append(message);
sendMessage.append("\r\n");
message = sendMessage.toString();
socket.send(Security.encrypt(message.getBytes(CHARSET)));
StringBuilder receiveMessage = new StringBuilder(receiveArea.getText());
receiveMessage.append(sendMessage);
receiveArea.setText(receiveMessage.toString());
sendTextArea.setText(null);
}
}
private void initSocket() throws SocketException {
socket = new UDPSocket(initDialog.getLocalHost(),initDialog.getRemoteHost(),initDialog.getReceivePort(),initDialog.getSendPort());
}
public void receive() throws UnsupportedEncodingException, IOException{
byte[] data = Security.decrypt(socket.receive());
String message = new String(data,CHARSET);
StringBuilder sb = new StringBuilder();
sb.append(receiveArea.getText());
sb.append(message);
receiveArea.setText(sb.toString());
}
public void run() {
while(true){
try {
receive();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) throws UnknownHostException, SocketException{
MainFrame mainFrame = new MainFrame();
Thread t = new Thread(mainFrame);
t.start();
}
}
public abstract class Security {
public static byte[] encrypt(byte[] data){
return Base64.encodeBase64(data);
}
public static byte[] decrypt(byte[] data){
return Base64.decodeBase64(data);
}
}