[JAVA加解密]对登陆密码及网络传输内容加密

所有源代码都在资源中有上传,这里我们主要构建了两个项目,第一个是一个简单的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);

实际上有了安全类之后,这么弄就行了。用wireshark无法再直接得到信息。


三、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();
		}
	}

初始化Dialog类:

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);
		
	}

}

这个类控制第一个界面,实际上就一个函数,给各种ip地址,端口赋值。通过监听器定义了俩button.



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);
	}

当然需要在new packet时指定发送到的主机和端口了

最细的也无非就是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();
	}

}


Security代码,这里只做了数据隐藏,加密同理,见之前章节

public abstract class Security {
	public static byte[] encrypt(byte[] data){
		return Base64.encodeBase64(data);
	}
	
	public static byte[] decrypt(byte[] data){
		return Base64.decodeBase64(data);
	}
}




你可能感兴趣的:(Java,加解密)