近日有项目需要将现有系统得TCP连接升级到加密的TLS连接,但是遇到得问题是,原来用得是SocketChannel等NIO类作为连接层。
但是众所周之,传统IO做SSL的话只要换Socket为SSLSocket就可以了,兼容原来的系统做
得很好
但是如果用了NIO,是没有一个叫做SSLSocketChannel的类的,如果想不大规模修改源代码的话,又不使用框架,就只可以使用jdk的SSLEngine类了。当然,工作量会非常大。这是一个很实际的需求,所以直接网上搜索资料去:
苦苦搜索之后在网上艰难地发现了一个实现了SSl的SocketChannel类,是属于某个开源框架的一部分,我从中抽离出来:
原链接如下,版权归原作者所有:
http://www.koders.com/java/fid3BBC1D50296CAB0AB23ED725C45FFBDC4A0EF698.aspx?s=cdef%3aftp+client
SSLSocketChannel.java:
/**
* Copyright (C) 2003 Alexander Kout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.kout.wlFxp;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import javax.net.ssl.*;
import java.io.*;
import de.kout.wlFxp.Utilities;
/**
* a SocketChannel with TLS/SSL encryption
*
*@author Alexander Kout
*@created 25. Mai 2005
*/
public class SSLSocketChannel {
int SSL;
ByteBuffer clientIn, clientOut, cTOs, sTOc, wbuf;
SocketChannel sc = null;
SSLEngineResult res;
SSLEngine sslEngine;
public SSLSocketChannel() throws IOException {
sc = SocketChannel.open();
}
public SSLSocketChannel(SocketChannel sc) {
this.sc = sc;
}
public int tryTLS(int pSSL) throws IOException {
SSL = pSSL;
if (SSL == 0)
return 0;
SSLContext sslContext=null;
try {
// create SSLContext
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,
new TrustManager[] {new EasyX509TrustManager(null)},
null);
// create Engine
sslEngine = sslContext.createSSLEngine();
// begin
sslEngine.setUseClientMode(true);
sslEngine.setEnableSessionCreation(true);
SSLSession session = sslEngine.getSession();
createBuffers(session);
// wrap
clientOut.clear();
sc.write(wrap(clientOut));
while (res.getHandshakeStatus() !=
SSLEngineResult.HandshakeStatus.FINISHED) {
if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
// unwrap
sTOc.clear();
while (sc.read(sTOc) < 1)
Thread.sleep(20);
sTOc.flip();
unwrap(sTOc);
if (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED) {
clientOut.clear();
sc.write(wrap(clientOut));
}
} else if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_WRAP) {
// wrap
clientOut.clear();
sc.write(wrap(clientOut));
} else {Thread.sleep(1000);}
}
clientIn.clear();
clientIn.flip();
SSL = 4;
Utilities.print("SSL established\n");
} catch (Exception e) {
e.printStackTrace(System.out);
SSL = 0;
}
return SSL;
}
private synchronized ByteBuffer wrap(ByteBuffer b) throws SSLException {
cTOs.clear();
res = sslEngine.wrap(b, cTOs);
cTOs.flip();
Utilities.print("wrap:\n"+res.toString()+"\n");
return cTOs;
}
private synchronized ByteBuffer unwrap(ByteBuffer b) throws SSLException {
clientIn.clear();
int pos;
Utilities.print("b.remaining "+b.remaining()+"\n");
while (b.hasRemaining()) {
Utilities.print("b.remaining "+b.remaining()+"\n");
res = sslEngine.unwrap(b, clientIn);
Utilities.print("unwrap:\n"+res.toString()+"\n");
if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_TASK) {
// Task
Runnable task;
while ((task=sslEngine.getDelegatedTask()) != null)
{
Utilities.print("task...\n");
task.run();
}
Utilities.print("task:\n"+res.toString()+"\n");
} else if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.FINISHED) {
return clientIn;
} else if (res.getStatus() ==
SSLEngineResult.Status.BUFFER_UNDERFLOW) {
Utilities.print("underflow\n");
Utilities.print("b.remaining "+b.remaining()+"\n");
return clientIn;
}
}
return clientIn;
}
private void createBuffers(SSLSession session) {
int appBufferMax = session.getApplicationBufferSize();
int netBufferMax = session.getPacketBufferSize();
clientIn = ByteBuffer.allocate(65536);
clientOut = ByteBuffer.allocate(appBufferMax);
wbuf = ByteBuffer.allocate(65536);
cTOs = ByteBuffer.allocate(netBufferMax);
sTOc = ByteBuffer.allocate(netBufferMax);
}
public int write(ByteBuffer src) throws IOException {
if (SSL == 4) {
return sc.write(wrap(src));
}
return sc.write(src);
}
public int read(ByteBuffer dst) throws IOException {
Utilities.print("read\n");
int amount = 0, limit;
if (SSL == 4) {
// test if there was a buffer overflow in dst
if (clientIn.hasRemaining()) {
limit = Math.min(clientIn.remaining(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
return amount;
}
// test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
if (sTOc.hasRemaining()) {
unwrap(sTOc);
clientIn.flip();
limit = Math.min(clientIn.limit(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
if (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW) {
sTOc.clear();
sTOc.flip();
return amount;
}
}
if (!sTOc.hasRemaining())
sTOc.clear();
else
sTOc.compact();
if (sc.read(sTOc) == -1) {
Utilities.print("close from SSLSocketChannel"+"\n");
sTOc.clear();
sTOc.flip();
return -1;
}
sTOc.flip();
unwrap(sTOc);
// write in dst
clientIn.flip();
limit = Math.min(clientIn.limit(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
Utilities.print("dst.remaining "+dst.remaining()+"\n");
return amount;
}
return sc.read(dst);
}
public boolean isConnected() {
return sc.isConnected();
}
public void close() throws IOException {
if (SSL == 4) {
sslEngine.closeOutbound();
clientOut.clear();
sc.write(wrap(clientOut));
sc.close();
} else
sc.close();
}
public SelectableChannel configureBlocking(boolean b) throws IOException {
return sc.configureBlocking(b);
}
public boolean connect(SocketAddress remote) throws IOException {
return sc.connect(remote);
}
public boolean finishConnect() throws IOException {
return sc.finishConnect();
}
public Socket socket() {
return sc.socket();
}
public boolean isInboundDone() {
return sslEngine.isInboundDone();
}
}
Utilities .java:
/**
* Copyright (C) 2003 Alexander Kout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.kout.wlFxp;
import java.text.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
//import de.kout.wlFxp.ftp.FtpFile;
/**
* Utility class
*
*@author Alexander Kout
*@created 30. M�rz 2002
*/
public class Utilities {
/**
* verbose output
*/
public static boolean debug = false;
/**
* the FileWriter for the debug mode
*/
public static FileWriter logFile = null;
private static final String[] monthsWS = {" Jan ", " Feb ", " Mar ", " Apr ",
" May ", " Jun ", " Jul ", " Aug ", " Sep ",
" Oct ", " Nov ", " Dec "};
private static final String[] months = {"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"};
/**
* transforms a long into a String like 4KiB
*
*@param size Description of Parameter
*@return Description of the Returned Value
*/
public static String humanReadable(double size) {
DecimalFormat df = new DecimalFormat("###0.00");
double f1;
double f2;
double f3;
if ((f1 = size / 1024.0) > 1.0) {
if ((f2 = f1 / 1024.0) > 1.0) {
if ((f3 = f2 / 1024) > 1.0) {
return df.format(f3) + "GiB";
}
return df.format(f2) + "MiB";
}
return df.format(f1) + "KiB";
}
return df.format(size) + "B";
}
/**
* Description of the Method
*
*@param size Description of Parameter
*@return Description of the Returned Value
*/
public static String humanReadable(long size) {
return humanReadable(size * 1.0);
}
public static String humanReadableTime(double time) {
DecimalFormat df = new DecimalFormat("###0");
double min, hour, day, sec;
sec = time *1.0;
StringBuffer buf = new StringBuffer(50);
// minutes
if ((min = sec /60.0) >= 1.0) {
// hours
if ((hour = min /60.0) >= 1.0) {
// days
if ((day = hour/24.0) >= 1.0) {
buf.append(df.format(day)).
append("d ").
append(df.format(hour-Math.floor(day)*24.0)).
append("h ").
append(df.format(min-Math.floor(hour)*60.0)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(hour)).
append("h ").
append(df.format(min-Math.floor(hour)*60.0)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(min)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(sec)).append("s");
return buf.toString();
}
public static String humanReadableTime2(double time) {
DecimalFormat df = new DecimalFormat("00");
double min, hour, day, sec;
sec = time *1.0;
StringBuffer buf = new StringBuffer(50);
// minutes
if ((min = sec /60.0) >= 1.0) {
// hours
if ((hour = min /60.0) >= 1.0) {
// days
if ((day = hour/24.0) >= 1.0) {
buf.append(df.format(day)).
append("d:").
append(df.format(hour-Math.floor(day)*24.0)).
append(":").
append(df.format(min-Math.floor(hour)*60.0)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(df.format(hour)).
append(":").
append(df.format(min-Math.floor(hour)*60.0)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(df.format(min)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(new DecimalFormat("#0").format(sec));
return buf.toString();
}
/**
* Heapsort "with bottom-up linear search" algorithm
*
*@param list must be a list of Strings
*/
public static void sortList(String list[]) {
// Heap creation
int n = list.length;
for (int i = n / 2; i > 0; i--) {
reheap(list, i, n);
}
for (int m = n; m > 0; m--) {
String t = list[0];
list[0] = list[m - 1];
list[m - 1] = t;
reheap(list, 1, m - 1);
}
}
/**
* reheap method for heapsort
*
*@param array String array to be sorted
*@param root position of root
*@param end position of end
*/
private static void reheap(String[] array, int root, int end) {
int[] stack = new int[new Double(Math.log(array.length) / Math.log(2)).intValue() + 10];
int s = 0;
int pos = root;
stack[s++] = pos;
while (2 * pos <= end) {
if (2 * pos + 1 > end) {
stack[s++] = 2 * pos;
break;
}
if (array[2 * pos - 1].compareToIgnoreCase(array[2 * pos]) > 0) {
stack[s++] = 2 * pos;
} else {
stack[s++] = 2 * pos + 1;
}
pos = stack[s - 1];
}
pos = root;
for (int i = s - 1; i >= 0; i--) {
if (array[stack[i] - 1].compareToIgnoreCase(array[root - 1]) > -1) {
pos = stack[i];
s = i + 1;
break;
}
}
String temp = array[root - 1];
for (int i = 1; i < s; i++) {
array[stack[i] / 2 - 1] = array[stack[i] - 1];
}
array[pos - 1] = temp;
}
/**
* Heapsort "with linear bottom-up search" algorithm
*
*@param list FtpFile array which is going to be sorted
*@param sortBy Description of the Parameter
*/
// public static void sortFiles(Vector list, String sortBy, boolean prio, Vector prioList) {
// // Heap creation
// int n = list.size();
// for (int i = n / 2; i > 0; i--) {
// reheap(list, i, n, sortBy, prio, prioList);
// }
// for (int m = n; m > 0; m--) {
// FtpFile t = (FtpFile) list.elementAt(0);
// list.setElementAt(list.elementAt(m - 1), 0);
// list.setElementAt(t, m-1);
// reheap(list, 1, m - 1, sortBy, prio, prioList);
// }
// }
/**
* reheap method for heapsort
*
*@param array array to be sorted
*@param root position of root
*@param end position of end
*@param sortBy Description of the Parameter
*/
// private static void reheap(Vector array, int root, int end, String sortBy, boolean prio, Vector prioList) {
// int[] stack = new int[new Double(Math.log(array.size()) / Math.log(2)).intValue() + 10];
// int s = 0;
// int pos = root;
// stack[s++] = pos;
// while (2 * pos <= end) {
// if (2 * pos + 1 > end) {
// stack[s++] = 2 * pos;
// break;
// }
// if (compareFiles(array.elementAt(2 * pos - 1), array.elementAt(2 * pos), sortBy, prio, prioList) > 0) {
// stack[s++] = 2 * pos;
// } else {
// stack[s++] = 2 * pos + 1;
// }
// pos = stack[s - 1];
// }
// pos = root;
// for (int i = s - 1; i >= 0; i--) {
// if (compareFiles(array.elementAt(stack[i] - 1), array.elementAt(root - 1), sortBy, prio, prioList) > -1) {
// pos = stack[i];
// s = i + 1;
// break;
// }
// }
//
// Object temp = array.elementAt(root - 1);
// for (int i = 1; i < s; i++) {
// array.setElementAt(array.elementAt(stack[i] - 1), stack[i] / 2 - 1);
// }
// array.setElementAt(temp, pos - 1);
// }
/**
* compare method for sorting
*
*@param f1 first file
*@param f2 second file
*@param sortBy Description of the Parameter
*@return result of compareToIgnoreCase
*/
// private static int compareFiles(Object o1, Object o2, String sortBy,boolean prio, Vector prioList) {
// int ret;
// FtpFile f1 = (FtpFile) o1;
// FtpFile f2 = (FtpFile) o2;
// if (prio) {
// int m1 = matches(prioList, f1.getName()), m2 = matches(prioList, f2.getName());
// if (m1 != -1 || m2 != -1) {
// if (m1 > m2) {
// return -1;
// }
// else if (m2 > m1) {
// return 1;
// }
// }
// }
// if (f1.isDirectory() && !f2.isDirectory()) {
// return -1;
// }
// if (!f1.isDirectory() && f2.isDirectory()) {
// return 1;
// }
// if (sortBy.equals("Name")) {
// return f1.getName().compareToIgnoreCase(f2.getName());
// } else if (sortBy.equals("IName")) {
// return -f1.getName().compareToIgnoreCase(f2.getName());
// } else if (sortBy.equals("Size")) {
// ret = (int) (f1.getSize() - f2.getSize());
// } else if (sortBy.equals("ISize")) {
// ret = (int) (f2.getSize() - f1.getSize());
// } else if (sortBy.equals("Date")) {
// if (f1.getDate().indexOf("/") == 2 && f2.getDate().indexOf("/") > 2) {
// return 1;
// } else if (f1.getDate().indexOf("/") > 2 && f2.getDate().indexOf("/") == 2) {
// return -1;
// }
// ret = f1.getDate().compareToIgnoreCase(f2.getDate());
// } else if (sortBy.equals("IDate")) {
// if (f1.getDate().indexOf("/") == 2 && f2.getDate().indexOf("/") > 2) {
// return -1;
// } else if (f1.getDate().indexOf("/") > 2 && f2.getDate().indexOf("/") == 2) {
// return 1;
// }
// ret = -f1.getDate().compareToIgnoreCase(f2.getDate());
// } else {
// return f1.getName().compareToIgnoreCase(f2.getName());
// }
// if (ret == 0) {
// ret = f1.getName().compareToIgnoreCase(f2.getName());
// }
// return ret;
// }
private static int matches(Vector v, String s) {
for (int i = 0; i < v.size(); i++) {
try {
if (Pattern.matches(((String) v.elementAt(i)).toLowerCase(), s.toLowerCase())) {
return (v.size()-i);
}
} catch (Exception e) {}
}
return -1;
}
/**
* print method which writes to a file if debug is true
*
*@param s String to be printed
*/
public static void print(String s) {
if (debug) {
String settings = System.getProperty("user.home", ".") + File.separator + ".wlFxp";
System.out.print(s);
try {
if (logFile == null) {
if (!new File(settings).isDirectory()) {
new File(settings).mkdir();
}
logFile = new FileWriter(settings + File.separator + "log.txt", true);
}
logFile.write(s);
logFile.flush();
} catch (IOException e) {
System.err.println(e.toString());
}
}
}
/**
* saves the stack trace of an exception
*
*@param e Description of the Parameter
*/
public static void saveStackTrace(Exception e) {
String settings = System.getProperty("user.home", ".") + File.separator + ".wlFxp" + File.separator + "logs";
try {
if (!new File(settings).isDirectory()) {
new File(settings).mkdirs();
}
FileWriter exceptionFile = new FileWriter(settings + File.separator + "exception: " + System.currentTimeMillis() / 1000);
StackTraceElement[] t = e.getStackTrace();
exceptionFile.write(e.toString() + "\n");
for (int i = 0; i < t.length; i++) {
exceptionFile.write(t[i].toString() + "\n");
}
exceptionFile.flush();
} catch (IOException ex) {
System.err.println(ex.toString());
}
}
/**
* parses the output of a list command into an array of FtpFiles
*
*@param output output of a LIST
*@param ftpDir directory of the LIST
*@return array of FtpFiles
*/
// public static Vector parseList(String output, String ftpDir) {
// String[] completeList = split(output, "\r\n");
// // FtpFile[] tmpfiles = new FtpFile[completeList.length];
// Vector files = new Vector(completeList.length, 100);
// FtpFile tmp;
// int k = 0;
// int index;
// for (int i = 0; i < completeList.length; i++) {
//// if (!Pattern.matches("([A-Za-z][A-Za-z][A-Za-z]) .[0-9] [0-9 ][0-9]", completeList[i]))
// // ...
// index = -1;
// int j = 0;
// int tindex = 0;
// while (j < monthsWS.length) {
// tindex = completeList[i].indexOf(monthsWS[j]);
// if (tindex != -1 && (index == -1 || tindex < index)) {
// index = tindex;
// }
// j++;
// }
// if (index == -1) {
// continue;
// }
//// System.out.println(index);
// tmp = new FtpFile("");
// files.addElement(tmp);
// if (completeList[i].indexOf(" -> ") != -1) {
// completeList[i] = completeList[i].substring(0, completeList[i].indexOf(" -> "));
// }
// tmp.setName(completeList[i].substring(
// completeList[i].substring(index + 10,
// completeList[i].length()).indexOf(" ")
// + 11 + index,
// completeList[i].length()));
// // if the server outputs the "." or ".." with list
// if (tmp.getName().equals(".")
// || tmp.getName().equals("..")) {
// files.removeElementAt(files.size()-1);
// continue;
// }
// tmp.setSize(Long.parseLong(completeList[i].substring(completeList[i].substring(0, index).lastIndexOf(" ") + 1, index)));
// tmp.setMode(completeList[i].substring(0, 10));
// tmp.setFtpMode(true);
// tmp.setDate(parseDate(completeList[i].substring(index, index + 13)));
// if (ftpDir.equals("/"))
// tmp.setAbsolutePath(ftpDir + tmp.getName());
// else
// tmp.setAbsolutePath(ftpDir +"/"+tmp.getName());
// k++;
// }
// return files;
// }
/**
* parses the dates of the LIST output into good looking Strings
*
*@param input Description of the Parameter
*@return Description of the Return Value
*/
private static String parseDate(String input) {
String[] tdate = split(input, " ");
String[] date = new String[3];
int k = 0;
for (int i = 0; i < tdate.length; i++) {
if (tdate[i].equals("")) {
continue;
}
date[k++] = tdate[i];
}
StringBuffer ret = new StringBuffer(30);
for (int j = 0; j < 12; j++) {
if (date[0].equals(months[j])) {
if (j < 9) {
// ret = "0" + (j + 1);
ret.append("0").append(j + 1);
} else {
// ret = (j + 1) + "";
ret.append(j + 1);
}
break;
}
}
int t = Integer.parseInt(date[1]);
if (t < 10) {
// ret += "/0" + t;
ret.append("/0").append(t);
} else {
// ret += "/" + t;
ret.append("/").append(t);
}
if (date[2].indexOf(":") != -1) {
// ret += " " + date[2];
ret.append(" ").append(date[2]);
} else {
// ret = date[2] + "/" + ret;
String tmp = ret.toString();
ret.delete(0, ret.length());
ret.append(date[2]).append("/").append(tmp);
}
return ret.toString();
}
/**
* parses the dates of local files into good looking Strings
*
*@param date Description of the Parameter
*@return Description of the Return Value
*/
public static String parseDate(long date) {
GregorianCalendar cal = new GregorianCalendar();
int curYear;
cal.setTime(new Date());
curYear = cal.get(Calendar.YEAR);
cal.setTime(new Date(date));
StringBuffer ret = new StringBuffer(30);
StringBuffer month = new StringBuffer(2);
month.append(cal.get(Calendar.MONTH) + 1);
if (month.length() == 1) {
month.insert(0, "0");
}
StringBuffer day = new StringBuffer(2);
day.append(cal.get(Calendar.DATE));
if (day.length() == 1) {
day.insert(0, "0");
}
StringBuffer hour = new StringBuffer(2);
hour.append(cal.get(Calendar.HOUR_OF_DAY));
if (hour.length() == 1) {
hour.insert(0, "0");
}
StringBuffer minute = new StringBuffer(2);
minute.append(cal.get(Calendar.MINUTE));
if (minute.length() == 1) {
minute.insert(0, "0");
}
if (curYear > cal.get(Calendar.YEAR)) {
// ret = "" + cal.get(Calendar.YEAR);
ret.append(cal.get(Calendar.YEAR)).append("/").append(month).append("/").append(day);
} else {
// ret = "" + month;
ret.append(month).append("/").append(day).append(" ").append(hour).append(":").append(minute);
}
return ret.toString();
}
/**
* rewrite of the split method from java.lang.String because it
* makes problems with gcj
*
*@param s Description of the Parameter
*@param key Description of the Parameter
*@return Description of the Return Value
*/
public static String[] split(String s, String key) {
Vector v = new Vector(100, 50);
while (s.length() > 0 && s.indexOf(key) != -1) {
v.addElement(s.substring(0, s.indexOf(key)));
s = s.substring(s.indexOf(key) + key.length(), s.length());
}
v.addElement(s);
while (v.size() > 0 && ((String) v.elementAt(v.size() - 1)).equals("")) {
v.removeElementAt(v.size() - 1);
}
String[] t = new String[v.size()];
for (int i = 0; i < v.size(); i++) {
t[i] = (String) v.elementAt(i);
}
return t;
}
/**
* no more errors with parsing ints with this method
*
*@param s Description of the Parameter
*@return Description of the Return Value
*/
public static int parseInt(String s) {
StringBuffer b = new StringBuffer(s.length());
for (int i = 0; i < s.length(); i++) {
if (Pattern.matches("[-0-9]", s.substring(i, i + 1))) {
b.append(s.substring(i, i + 1));
}
}
return Integer.parseInt(b.toString());
}
}
EasyX509TrustManager.java:
package de.kout.wlFxp;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
public EasyX509TrustManager(KeyStore keystore)
throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory
.getInstance("SunX509");
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException(
"SunX509 trust manager not supported");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
public void checkClientTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
this.standardTrustManager.checkClientTrusted(certificates, authType);
}
public void checkServerTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
X509Certificate certificate = certificates[0];
try {
certificate.checkValidity();
} catch (CertificateException e) {
}
} else {
this.standardTrustManager
.checkServerTrusted(certificates, authType);
}
}
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
用法:
用旧 SocketChannel作为参数构建SSLSocketChannel
然后,tryTLS(1)
但是众所周之,传统IO做SSL的话只要换Socket为SSLSocket就可以了,兼容原来的系统做
得很好
但是如果用了NIO,是没有一个叫做SSLSocketChannel的类的,如果想不大规模修改源代码的话,又不使用框架,就只可以使用jdk的SSLEngine类了。当然,工作量会非常大。这是一个很实际的需求,所以直接网上搜索资料去:
苦苦搜索之后在网上艰难地发现了一个实现了SSl的SocketChannel类,是属于某个开源框架的一部分,我从中抽离出来:
原链接如下,版权归原作者所有:
http://www.koders.com/java/fid3BBC1D50296CAB0AB23ED725C45FFBDC4A0EF698.aspx?s=cdef%3aftp+client
SSLSocketChannel.java:
/**
* Copyright (C) 2003 Alexander Kout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.kout.wlFxp;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import javax.net.ssl.*;
import java.io.*;
import de.kout.wlFxp.Utilities;
/**
* a SocketChannel with TLS/SSL encryption
*
*@author Alexander Kout
*@created 25. Mai 2005
*/
public class SSLSocketChannel {
int SSL;
ByteBuffer clientIn, clientOut, cTOs, sTOc, wbuf;
SocketChannel sc = null;
SSLEngineResult res;
SSLEngine sslEngine;
public SSLSocketChannel() throws IOException {
sc = SocketChannel.open();
}
public SSLSocketChannel(SocketChannel sc) {
this.sc = sc;
}
public int tryTLS(int pSSL) throws IOException {
SSL = pSSL;
if (SSL == 0)
return 0;
SSLContext sslContext=null;
try {
// create SSLContext
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,
new TrustManager[] {new EasyX509TrustManager(null)},
null);
// create Engine
sslEngine = sslContext.createSSLEngine();
// begin
sslEngine.setUseClientMode(true);
sslEngine.setEnableSessionCreation(true);
SSLSession session = sslEngine.getSession();
createBuffers(session);
// wrap
clientOut.clear();
sc.write(wrap(clientOut));
while (res.getHandshakeStatus() !=
SSLEngineResult.HandshakeStatus.FINISHED) {
if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
// unwrap
sTOc.clear();
while (sc.read(sTOc) < 1)
Thread.sleep(20);
sTOc.flip();
unwrap(sTOc);
if (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED) {
clientOut.clear();
sc.write(wrap(clientOut));
}
} else if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_WRAP) {
// wrap
clientOut.clear();
sc.write(wrap(clientOut));
} else {Thread.sleep(1000);}
}
clientIn.clear();
clientIn.flip();
SSL = 4;
Utilities.print("SSL established\n");
} catch (Exception e) {
e.printStackTrace(System.out);
SSL = 0;
}
return SSL;
}
private synchronized ByteBuffer wrap(ByteBuffer b) throws SSLException {
cTOs.clear();
res = sslEngine.wrap(b, cTOs);
cTOs.flip();
Utilities.print("wrap:\n"+res.toString()+"\n");
return cTOs;
}
private synchronized ByteBuffer unwrap(ByteBuffer b) throws SSLException {
clientIn.clear();
int pos;
Utilities.print("b.remaining "+b.remaining()+"\n");
while (b.hasRemaining()) {
Utilities.print("b.remaining "+b.remaining()+"\n");
res = sslEngine.unwrap(b, clientIn);
Utilities.print("unwrap:\n"+res.toString()+"\n");
if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.NEED_TASK) {
// Task
Runnable task;
while ((task=sslEngine.getDelegatedTask()) != null)
{
Utilities.print("task...\n");
task.run();
}
Utilities.print("task:\n"+res.toString()+"\n");
} else if (res.getHandshakeStatus() ==
SSLEngineResult.HandshakeStatus.FINISHED) {
return clientIn;
} else if (res.getStatus() ==
SSLEngineResult.Status.BUFFER_UNDERFLOW) {
Utilities.print("underflow\n");
Utilities.print("b.remaining "+b.remaining()+"\n");
return clientIn;
}
}
return clientIn;
}
private void createBuffers(SSLSession session) {
int appBufferMax = session.getApplicationBufferSize();
int netBufferMax = session.getPacketBufferSize();
clientIn = ByteBuffer.allocate(65536);
clientOut = ByteBuffer.allocate(appBufferMax);
wbuf = ByteBuffer.allocate(65536);
cTOs = ByteBuffer.allocate(netBufferMax);
sTOc = ByteBuffer.allocate(netBufferMax);
}
public int write(ByteBuffer src) throws IOException {
if (SSL == 4) {
return sc.write(wrap(src));
}
return sc.write(src);
}
public int read(ByteBuffer dst) throws IOException {
Utilities.print("read\n");
int amount = 0, limit;
if (SSL == 4) {
// test if there was a buffer overflow in dst
if (clientIn.hasRemaining()) {
limit = Math.min(clientIn.remaining(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
return amount;
}
// test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
if (sTOc.hasRemaining()) {
unwrap(sTOc);
clientIn.flip();
limit = Math.min(clientIn.limit(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
if (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW) {
sTOc.clear();
sTOc.flip();
return amount;
}
}
if (!sTOc.hasRemaining())
sTOc.clear();
else
sTOc.compact();
if (sc.read(sTOc) == -1) {
Utilities.print("close from SSLSocketChannel"+"\n");
sTOc.clear();
sTOc.flip();
return -1;
}
sTOc.flip();
unwrap(sTOc);
// write in dst
clientIn.flip();
limit = Math.min(clientIn.limit(), dst.remaining());
for (int i = 0; i < limit; i++) {
dst.put(clientIn.get());
amount++;
}
Utilities.print("dst.remaining "+dst.remaining()+"\n");
return amount;
}
return sc.read(dst);
}
public boolean isConnected() {
return sc.isConnected();
}
public void close() throws IOException {
if (SSL == 4) {
sslEngine.closeOutbound();
clientOut.clear();
sc.write(wrap(clientOut));
sc.close();
} else
sc.close();
}
public SelectableChannel configureBlocking(boolean b) throws IOException {
return sc.configureBlocking(b);
}
public boolean connect(SocketAddress remote) throws IOException {
return sc.connect(remote);
}
public boolean finishConnect() throws IOException {
return sc.finishConnect();
}
public Socket socket() {
return sc.socket();
}
public boolean isInboundDone() {
return sslEngine.isInboundDone();
}
}
Utilities .java:
/**
* Copyright (C) 2003 Alexander Kout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.kout.wlFxp;
import java.text.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
//import de.kout.wlFxp.ftp.FtpFile;
/**
* Utility class
*
*@author Alexander Kout
*@created 30. M�rz 2002
*/
public class Utilities {
/**
* verbose output
*/
public static boolean debug = false;
/**
* the FileWriter for the debug mode
*/
public static FileWriter logFile = null;
private static final String[] monthsWS = {" Jan ", " Feb ", " Mar ", " Apr ",
" May ", " Jun ", " Jul ", " Aug ", " Sep ",
" Oct ", " Nov ", " Dec "};
private static final String[] months = {"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"};
/**
* transforms a long into a String like 4KiB
*
*@param size Description of Parameter
*@return Description of the Returned Value
*/
public static String humanReadable(double size) {
DecimalFormat df = new DecimalFormat("###0.00");
double f1;
double f2;
double f3;
if ((f1 = size / 1024.0) > 1.0) {
if ((f2 = f1 / 1024.0) > 1.0) {
if ((f3 = f2 / 1024) > 1.0) {
return df.format(f3) + "GiB";
}
return df.format(f2) + "MiB";
}
return df.format(f1) + "KiB";
}
return df.format(size) + "B";
}
/**
* Description of the Method
*
*@param size Description of Parameter
*@return Description of the Returned Value
*/
public static String humanReadable(long size) {
return humanReadable(size * 1.0);
}
public static String humanReadableTime(double time) {
DecimalFormat df = new DecimalFormat("###0");
double min, hour, day, sec;
sec = time *1.0;
StringBuffer buf = new StringBuffer(50);
// minutes
if ((min = sec /60.0) >= 1.0) {
// hours
if ((hour = min /60.0) >= 1.0) {
// days
if ((day = hour/24.0) >= 1.0) {
buf.append(df.format(day)).
append("d ").
append(df.format(hour-Math.floor(day)*24.0)).
append("h ").
append(df.format(min-Math.floor(hour)*60.0)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(hour)).
append("h ").
append(df.format(min-Math.floor(hour)*60.0)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(min)).
append("min ").
append(df.format(sec-Math.floor(min)*60.0)).
append("s");
return buf.toString();
}
buf.append(df.format(sec)).append("s");
return buf.toString();
}
public static String humanReadableTime2(double time) {
DecimalFormat df = new DecimalFormat("00");
double min, hour, day, sec;
sec = time *1.0;
StringBuffer buf = new StringBuffer(50);
// minutes
if ((min = sec /60.0) >= 1.0) {
// hours
if ((hour = min /60.0) >= 1.0) {
// days
if ((day = hour/24.0) >= 1.0) {
buf.append(df.format(day)).
append("d:").
append(df.format(hour-Math.floor(day)*24.0)).
append(":").
append(df.format(min-Math.floor(hour)*60.0)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(df.format(hour)).
append(":").
append(df.format(min-Math.floor(hour)*60.0)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(df.format(min)).
append(":").
append(df.format(sec-Math.floor(min)*60.0));
return buf.toString();
}
buf.append(new DecimalFormat("#0").format(sec));
return buf.toString();
}
/**
* Heapsort "with bottom-up linear search" algorithm
*
*@param list must be a list of Strings
*/
public static void sortList(String list[]) {
// Heap creation
int n = list.length;
for (int i = n / 2; i > 0; i--) {
reheap(list, i, n);
}
for (int m = n; m > 0; m--) {
String t = list[0];
list[0] = list[m - 1];
list[m - 1] = t;
reheap(list, 1, m - 1);
}
}
/**
* reheap method for heapsort
*
*@param array String array to be sorted
*@param root position of root
*@param end position of end
*/
private static void reheap(String[] array, int root, int end) {
int[] stack = new int[new Double(Math.log(array.length) / Math.log(2)).intValue() + 10];
int s = 0;
int pos = root;
stack[s++] = pos;
while (2 * pos <= end) {
if (2 * pos + 1 > end) {
stack[s++] = 2 * pos;
break;
}
if (array[2 * pos - 1].compareToIgnoreCase(array[2 * pos]) > 0) {
stack[s++] = 2 * pos;
} else {
stack[s++] = 2 * pos + 1;
}
pos = stack[s - 1];
}
pos = root;
for (int i = s - 1; i >= 0; i--) {
if (array[stack[i] - 1].compareToIgnoreCase(array[root - 1]) > -1) {
pos = stack[i];
s = i + 1;
break;
}
}
String temp = array[root - 1];
for (int i = 1; i < s; i++) {
array[stack[i] / 2 - 1] = array[stack[i] - 1];
}
array[pos - 1] = temp;
}
/**
* Heapsort "with linear bottom-up search" algorithm
*
*@param list FtpFile array which is going to be sorted
*@param sortBy Description of the Parameter
*/
// public static void sortFiles(Vector list, String sortBy, boolean prio, Vector prioList) {
// // Heap creation
// int n = list.size();
// for (int i = n / 2; i > 0; i--) {
// reheap(list, i, n, sortBy, prio, prioList);
// }
// for (int m = n; m > 0; m--) {
// FtpFile t = (FtpFile) list.elementAt(0);
// list.setElementAt(list.elementAt(m - 1), 0);
// list.setElementAt(t, m-1);
// reheap(list, 1, m - 1, sortBy, prio, prioList);
// }
// }
/**
* reheap method for heapsort
*
*@param array array to be sorted
*@param root position of root
*@param end position of end
*@param sortBy Description of the Parameter
*/
// private static void reheap(Vector array, int root, int end, String sortBy, boolean prio, Vector prioList) {
// int[] stack = new int[new Double(Math.log(array.size()) / Math.log(2)).intValue() + 10];
// int s = 0;
// int pos = root;
// stack[s++] = pos;
// while (2 * pos <= end) {
// if (2 * pos + 1 > end) {
// stack[s++] = 2 * pos;
// break;
// }
// if (compareFiles(array.elementAt(2 * pos - 1), array.elementAt(2 * pos), sortBy, prio, prioList) > 0) {
// stack[s++] = 2 * pos;
// } else {
// stack[s++] = 2 * pos + 1;
// }
// pos = stack[s - 1];
// }
// pos = root;
// for (int i = s - 1; i >= 0; i--) {
// if (compareFiles(array.elementAt(stack[i] - 1), array.elementAt(root - 1), sortBy, prio, prioList) > -1) {
// pos = stack[i];
// s = i + 1;
// break;
// }
// }
//
// Object temp = array.elementAt(root - 1);
// for (int i = 1; i < s; i++) {
// array.setElementAt(array.elementAt(stack[i] - 1), stack[i] / 2 - 1);
// }
// array.setElementAt(temp, pos - 1);
// }
/**
* compare method for sorting
*
*@param f1 first file
*@param f2 second file
*@param sortBy Description of the Parameter
*@return result of compareToIgnoreCase
*/
// private static int compareFiles(Object o1, Object o2, String sortBy,boolean prio, Vector prioList) {
// int ret;
// FtpFile f1 = (FtpFile) o1;
// FtpFile f2 = (FtpFile) o2;
// if (prio) {
// int m1 = matches(prioList, f1.getName()), m2 = matches(prioList, f2.getName());
// if (m1 != -1 || m2 != -1) {
// if (m1 > m2) {
// return -1;
// }
// else if (m2 > m1) {
// return 1;
// }
// }
// }
// if (f1.isDirectory() && !f2.isDirectory()) {
// return -1;
// }
// if (!f1.isDirectory() && f2.isDirectory()) {
// return 1;
// }
// if (sortBy.equals("Name")) {
// return f1.getName().compareToIgnoreCase(f2.getName());
// } else if (sortBy.equals("IName")) {
// return -f1.getName().compareToIgnoreCase(f2.getName());
// } else if (sortBy.equals("Size")) {
// ret = (int) (f1.getSize() - f2.getSize());
// } else if (sortBy.equals("ISize")) {
// ret = (int) (f2.getSize() - f1.getSize());
// } else if (sortBy.equals("Date")) {
// if (f1.getDate().indexOf("/") == 2 && f2.getDate().indexOf("/") > 2) {
// return 1;
// } else if (f1.getDate().indexOf("/") > 2 && f2.getDate().indexOf("/") == 2) {
// return -1;
// }
// ret = f1.getDate().compareToIgnoreCase(f2.getDate());
// } else if (sortBy.equals("IDate")) {
// if (f1.getDate().indexOf("/") == 2 && f2.getDate().indexOf("/") > 2) {
// return -1;
// } else if (f1.getDate().indexOf("/") > 2 && f2.getDate().indexOf("/") == 2) {
// return 1;
// }
// ret = -f1.getDate().compareToIgnoreCase(f2.getDate());
// } else {
// return f1.getName().compareToIgnoreCase(f2.getName());
// }
// if (ret == 0) {
// ret = f1.getName().compareToIgnoreCase(f2.getName());
// }
// return ret;
// }
private static int matches(Vector v, String s) {
for (int i = 0; i < v.size(); i++) {
try {
if (Pattern.matches(((String) v.elementAt(i)).toLowerCase(), s.toLowerCase())) {
return (v.size()-i);
}
} catch (Exception e) {}
}
return -1;
}
/**
* print method which writes to a file if debug is true
*
*@param s String to be printed
*/
public static void print(String s) {
if (debug) {
String settings = System.getProperty("user.home", ".") + File.separator + ".wlFxp";
System.out.print(s);
try {
if (logFile == null) {
if (!new File(settings).isDirectory()) {
new File(settings).mkdir();
}
logFile = new FileWriter(settings + File.separator + "log.txt", true);
}
logFile.write(s);
logFile.flush();
} catch (IOException e) {
System.err.println(e.toString());
}
}
}
/**
* saves the stack trace of an exception
*
*@param e Description of the Parameter
*/
public static void saveStackTrace(Exception e) {
String settings = System.getProperty("user.home", ".") + File.separator + ".wlFxp" + File.separator + "logs";
try {
if (!new File(settings).isDirectory()) {
new File(settings).mkdirs();
}
FileWriter exceptionFile = new FileWriter(settings + File.separator + "exception: " + System.currentTimeMillis() / 1000);
StackTraceElement[] t = e.getStackTrace();
exceptionFile.write(e.toString() + "\n");
for (int i = 0; i < t.length; i++) {
exceptionFile.write(t[i].toString() + "\n");
}
exceptionFile.flush();
} catch (IOException ex) {
System.err.println(ex.toString());
}
}
/**
* parses the output of a list command into an array of FtpFiles
*
*@param output output of a LIST
*@param ftpDir directory of the LIST
*@return array of FtpFiles
*/
// public static Vector parseList(String output, String ftpDir) {
// String[] completeList = split(output, "\r\n");
// // FtpFile[] tmpfiles = new FtpFile[completeList.length];
// Vector files = new Vector(completeList.length, 100);
// FtpFile tmp;
// int k = 0;
// int index;
// for (int i = 0; i < completeList.length; i++) {
//// if (!Pattern.matches("([A-Za-z][A-Za-z][A-Za-z]) .[0-9] [0-9 ][0-9]", completeList[i]))
// // ...
// index = -1;
// int j = 0;
// int tindex = 0;
// while (j < monthsWS.length) {
// tindex = completeList[i].indexOf(monthsWS[j]);
// if (tindex != -1 && (index == -1 || tindex < index)) {
// index = tindex;
// }
// j++;
// }
// if (index == -1) {
// continue;
// }
//// System.out.println(index);
// tmp = new FtpFile("");
// files.addElement(tmp);
// if (completeList[i].indexOf(" -> ") != -1) {
// completeList[i] = completeList[i].substring(0, completeList[i].indexOf(" -> "));
// }
// tmp.setName(completeList[i].substring(
// completeList[i].substring(index + 10,
// completeList[i].length()).indexOf(" ")
// + 11 + index,
// completeList[i].length()));
// // if the server outputs the "." or ".." with list
// if (tmp.getName().equals(".")
// || tmp.getName().equals("..")) {
// files.removeElementAt(files.size()-1);
// continue;
// }
// tmp.setSize(Long.parseLong(completeList[i].substring(completeList[i].substring(0, index).lastIndexOf(" ") + 1, index)));
// tmp.setMode(completeList[i].substring(0, 10));
// tmp.setFtpMode(true);
// tmp.setDate(parseDate(completeList[i].substring(index, index + 13)));
// if (ftpDir.equals("/"))
// tmp.setAbsolutePath(ftpDir + tmp.getName());
// else
// tmp.setAbsolutePath(ftpDir +"/"+tmp.getName());
// k++;
// }
// return files;
// }
/**
* parses the dates of the LIST output into good looking Strings
*
*@param input Description of the Parameter
*@return Description of the Return Value
*/
private static String parseDate(String input) {
String[] tdate = split(input, " ");
String[] date = new String[3];
int k = 0;
for (int i = 0; i < tdate.length; i++) {
if (tdate[i].equals("")) {
continue;
}
date[k++] = tdate[i];
}
StringBuffer ret = new StringBuffer(30);
for (int j = 0; j < 12; j++) {
if (date[0].equals(months[j])) {
if (j < 9) {
// ret = "0" + (j + 1);
ret.append("0").append(j + 1);
} else {
// ret = (j + 1) + "";
ret.append(j + 1);
}
break;
}
}
int t = Integer.parseInt(date[1]);
if (t < 10) {
// ret += "/0" + t;
ret.append("/0").append(t);
} else {
// ret += "/" + t;
ret.append("/").append(t);
}
if (date[2].indexOf(":") != -1) {
// ret += " " + date[2];
ret.append(" ").append(date[2]);
} else {
// ret = date[2] + "/" + ret;
String tmp = ret.toString();
ret.delete(0, ret.length());
ret.append(date[2]).append("/").append(tmp);
}
return ret.toString();
}
/**
* parses the dates of local files into good looking Strings
*
*@param date Description of the Parameter
*@return Description of the Return Value
*/
public static String parseDate(long date) {
GregorianCalendar cal = new GregorianCalendar();
int curYear;
cal.setTime(new Date());
curYear = cal.get(Calendar.YEAR);
cal.setTime(new Date(date));
StringBuffer ret = new StringBuffer(30);
StringBuffer month = new StringBuffer(2);
month.append(cal.get(Calendar.MONTH) + 1);
if (month.length() == 1) {
month.insert(0, "0");
}
StringBuffer day = new StringBuffer(2);
day.append(cal.get(Calendar.DATE));
if (day.length() == 1) {
day.insert(0, "0");
}
StringBuffer hour = new StringBuffer(2);
hour.append(cal.get(Calendar.HOUR_OF_DAY));
if (hour.length() == 1) {
hour.insert(0, "0");
}
StringBuffer minute = new StringBuffer(2);
minute.append(cal.get(Calendar.MINUTE));
if (minute.length() == 1) {
minute.insert(0, "0");
}
if (curYear > cal.get(Calendar.YEAR)) {
// ret = "" + cal.get(Calendar.YEAR);
ret.append(cal.get(Calendar.YEAR)).append("/").append(month).append("/").append(day);
} else {
// ret = "" + month;
ret.append(month).append("/").append(day).append(" ").append(hour).append(":").append(minute);
}
return ret.toString();
}
/**
* rewrite of the split method from java.lang.String because it
* makes problems with gcj
*
*@param s Description of the Parameter
*@param key Description of the Parameter
*@return Description of the Return Value
*/
public static String[] split(String s, String key) {
Vector v = new Vector(100, 50);
while (s.length() > 0 && s.indexOf(key) != -1) {
v.addElement(s.substring(0, s.indexOf(key)));
s = s.substring(s.indexOf(key) + key.length(), s.length());
}
v.addElement(s);
while (v.size() > 0 && ((String) v.elementAt(v.size() - 1)).equals("")) {
v.removeElementAt(v.size() - 1);
}
String[] t = new String[v.size()];
for (int i = 0; i < v.size(); i++) {
t[i] = (String) v.elementAt(i);
}
return t;
}
/**
* no more errors with parsing ints with this method
*
*@param s Description of the Parameter
*@return Description of the Return Value
*/
public static int parseInt(String s) {
StringBuffer b = new StringBuffer(s.length());
for (int i = 0; i < s.length(); i++) {
if (Pattern.matches("[-0-9]", s.substring(i, i + 1))) {
b.append(s.substring(i, i + 1));
}
}
return Integer.parseInt(b.toString());
}
}
EasyX509TrustManager.java:
package de.kout.wlFxp;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
public EasyX509TrustManager(KeyStore keystore)
throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory
.getInstance("SunX509");
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException(
"SunX509 trust manager not supported");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
public void checkClientTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
this.standardTrustManager.checkClientTrusted(certificates, authType);
}
public void checkServerTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
X509Certificate certificate = certificates[0];
try {
certificate.checkValidity();
} catch (CertificateException e) {
}
} else {
this.standardTrustManager
.checkServerTrusted(certificates, authType);
}
}
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
用法:
用旧 SocketChannel作为参数构建SSLSocketChannel
然后,tryTLS(1)
相关推荐
在本篇博文中,我们将深入探讨如何利用Apache MINA库实现基于TLS/SSL的NIO(非阻塞I/O)Socket通信。MINA是一个高度可扩展的网络应用框架,广泛用于构建高性能、高并发的网络应用程序,如服务器端的TCP和UDP服务。...
这个包允许用户编写协议客户端和服务器,使用 TLS 来保护飞行中的数据。 该名称主要受此包使用的库名称 (BoringSSL) 的启发,而不是因为我们不知道协议的名称。 我们知道协议是 TLS! 要开始,请查看。使用 ...
- 考虑到安全,可能会使用SSL/TLS对通信进行加密。 - 为了提高性能,可以使用零拷贝(Zero-Copy)技术,减少数据在内存间的复制,提高网络I/O效率。 7. **异常处理** - NIO操作中,必须妥善处理各种可能的异常,...
10. **安全性与异常处理**: 考虑到网络通信的不可靠性,客户端需要适当地处理连接失败、数据传输错误以及安全问题,例如使用SSL/TLS协议进行加密通信。 在压缩包中的`JavaNioTamplateClient`可能是实现以上概念的一...
虽然NioSocket使用了NIO技术,但在某些情况下,开发者可能需要结合Java Socket API来完成特定任务,例如实现SSL/TLS加密通信。 总之,NioSocket是一个高效且适用于高并发环境的网络通信解决方案,它的设计包含了...
同时,为了保证安全性,需要关注数据传输的安全性,可能需要启用SSL/TLS加密,防止数据在传输过程中被窃取。 总的来说,鹊桥(MagpieBridge)是开发者解决内网服务对外访问问题的一个利器,它利用Java的NIO/AIO技术...
5. **套接字通道的改进**:如支持IPv6,以及SSL/TLS加密的套接字通道。 综上所述,Java NIO 和 NIO.2 提供了强大的工具和机制,使得开发者能够构建高并发、低延迟的系统。通过学习这两部分的内容,开发者可以更好地...
8. **NIO与TLS**:Java的非阻塞I/O(New IO,NIO)框架也可以与TLS结合使用,提供异步的加密通信。通过`SSLEngine`类,可以在`Selector`和`Channel`上实现TLS功能。 9. **HTTPS与TLS**:HTTPS是HTTP协议的安全版本...
7. **安全性**:考虑到网络安全,源码可能包含了SSL/TLS支持,通过SocketChannel的configureBlocking()方法设置为非阻塞模式,并使用SSLEngine处理加密通信。 这个聊天室项目不仅展示了Java NIO的基本用法,还可能...
Java平台提供了丰富的IO和NIO API,但它们的使用往往相对复杂,需要对底层机制有深入理解。本文将详细介绍如何封装Java IO和NIO,以及基于此封装的HTTP客户端的实现。 首先,让我们了解一下Java的IO和NIO。Java IO...
Mina的目标是简化网络服务开发,提供了一种统一的API,用于处理TCP/IP、UDP和SSL/TLS等不同协议。 首先,我们需要理解Java NIO的工作机制。传统的Java IO基于阻塞I/O模型,即一个线程在等待数据读取或写入时会被...
- **SSL支持**:内置SSL/TLS加密支持,保障数据传输的安全性。 - **流量控制与攻击防御**:提供了一系列安全措施,防止恶意攻击,如DoS攻击等。 - **Mock测试与JMX监控**:支持模拟测试环境下的单元测试,以及通过...
在本项目"chacha.rar_NIO soclet java_java nio"中,开发者使用Java NIO实现了一个用户动态口令的认证系统,并结合了MongoDB数据库来存储和管理数据。 1. **Java NIO基础**: - **通道(Channels)**:NIO的核心...
它支持多种协议,包括TCP、UDP,还支持SSL/TLS加密。Mina提供了事件驱动和异步的模型,使得开发复杂网络应用变得简单,同时具备了NIO的高性能特性。 在服务端,无论是Socket、NIO还是Mina,都需要创建监听套接字来...
在NIO中,通常会使用Selector来管理多个通道,以便于异步检测它们的读写就绪状态。 对于HTTPS连接,Java的`javax.net.ssl.SSLContext`类用于初始化和管理SSL/TLS协议,`javax.net.ssl.SSLEngine`则用于处理实际的...
在`Socket`通信中,`NIO Socket`使用`SocketChannel`代替了`Socket`,`ServerSocketChannel`代替了`ServerSocket`。客户端通过`SocketChannel`连接服务器,服务器端则通过`ServerSocketChannel`监听客户端的连接请求...
- **利用NIO的非阻塞性质**:在设计SSL/TLS层时充分利用非阻塞I/O的特点,确保即使在网络通信密集型的应用场景下也能保持高性能。 #### 总结 在本次演讲中,我们深入探讨了如何有效地使用Java NIO技术以及Project...
HTTP是无状态的,适用于快速交换信息,而HTTPS在HTTP的基础上加入了SSL/TLS加密,保证了数据的安全性。该工具支持HTTP通信测试,意味着开发者可以验证其应用的Web接口是否正常工作,同时也能检查HTTPS的安全性能。 ...
在给定的标题“使用Java基于Netty+Socks5+TLS实现的代理服务.zip”中,我们可以看到三个核心概念:Netty、Socks5和TLS,这些都是构建高效、安全网络服务的关键组件。 Netty是一个高性能、异步事件驱动的网络应用...