luncrzs 发布的文章

生成CA和服务器证书

一、生成ca证书
a) 创建一个证书目录,mkdir /home/ubuntu/SSL
b) 将CA.sh拷贝到/home/ubuntu/SSL目录,cp /usr/lib/ssl/misc/CA.sh /home/ubuntu/SSL
c) ./CA.sh -newca
d) 根据提示填写信息完成后,在demoCA下会生成证书文件,其中demoCA/private/cakey.pem为ca证书私钥,demoCA/cacert.pem为ca根证书。

二、生成服务器证书
a) 生成私钥: openssl genrsa -des3 -out server.key 1024
b) 生成csr文件: openssl req -new -key server.key -out server.csr
c) 生成证书&签名: openssl ca -in server.csr -out server.crt

三、生成客户端证书
a) 生成私钥: openssl genrsa -des3 -out client.key 1024
b) 生成csr文件: openssl req -new -key client.key -out client.csr
c) 生成证书&签名: openssl ca -in client.csr -out client.crt

四、生成不带密码验证的
如果你想要把数字证书用于Nginx、Apache等Web服务器,你会发现启动nginx服务器时会要求你输入数字证书密码,这是因为在设置私钥key时将密码写入了key文件,导致Nginx/Apache等系列服务器在启动时要求Enter PEM pass phrase。我们需要做的是剥离这个密码,利用如下OpenSSL命令生成server.key.unsecure文件
openssl rsa -in server.key -out server.key.unsecure

安卓WSS客户端

  • 在app模块build.gradle中添加依赖
compile 'org.java-websocket:Java-WebSocket:1.3.0'
  • 实现WebSocketClien接口
public class WSS extends WebSocketClient {

    public static WSS newInstance(){
        WSS wss = null;
        try{
            wss = new WSS(new URI(Config.CHAT_SOCKET_ADDR));
        }catch (Exception e){
        }
        return wss;
    }

    public WSS(URI uri){
        super(uri);
        TrustManager[] trustAllCerts = new TrustManager[] { new TrustManager()};
        try{
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sc));
        }catch (Exception ignored){}
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
    }

    @Override
    public void onMessage(String message) {
    }

    @Override
    public void onError(Exception ex) {
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
    }
}
  • 实现X509TrustManager
public class TrustManager implements X509TrustManager {

    private Certificate ca = null;

    public TrustManager(){
        try{
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = new BufferedInputStream(MyApplication.getApplication().getAssets().open("ca.crt"));
            try {
                ca = cf.generateCertificate(caInput);
            }finally {
                caInput.close();
            }
        } catch (CertificateException e1){
            e1.printStackTrace();
        } catch (IOException e2){
            e2.printStackTrace();
        }
    }

    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[] {};
    }

    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
        for (X509Certificate cert : chain) {
            cert.checkValidity();
            try {
                cert.verify(((X509Certificate) ca).getPublicKey());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            } catch (SignatureException e) {
                e.printStackTrace();
            }
        }
    }
}

Nginx反向代理慢解决办法

在配置nginx反向代理时upstream里面server用localhost:端口,非常慢,看log,默认将localhost解析成ipv6的地址,故出现此问题,改成127.0.0.1后问题解决。
后端被代理网络应用使用Delphi开发

Get process name in Android

public static String getProcessName() {
  try {
    File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
    BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
    String processName = mBufferedReader.readLine().trim();
    mBufferedReader.close();
    return processName;
  } catch (Exception e) {
    e.printStackTrace();
    return null;
  }
}

JAVA神奇又强大的反射

最近在写安卓项目的时候遇到一个很棘手的问题,AsyncTask的某一个task似乎被前一个task卡住了很久,应该是之前的task执行了一些非常耗时的操作,使得后面的task一直被卡住。查看源码后发现那个代码中用的是execute()方法而不是executeOnExecutor,所以使用的是默认的SERIAL_EXECUTOR,我理所当然地认为是某个地方使用了SERIAL_EXECUTOR然后用时太长导致后面的task都被卡住,所以把项目里用execute的地方都改成了executeOnExecutor,发现问题没解决。苦于没有解决办法,拖了几天没看。今天再去看代码的时候神奇的发现SERIAL_EXECUTOR使用的居然也是THREAD_POOL_EXECUTOR,只不过内部做了一个serial处理,我就更加疑惑了,怎么用了线程池还会被卡住呢。。。

我就在想,如果有什么办法可以在THREAD_POOL_EXECUTOR执行execute的方法的时候printStackTrace一下就好了,然后突发其想能不能利用java的反射原理把AsyncTask的THREAD_POOL_EXECUTOR替换成我自己的,这样我就可以打log了,上网搜索了一下,果然可以,真是太强大了。

打log发现是一个第三方sdk用AsyncTask来执行网络连接,然后很长时间都没能连到服务器,导致被卡住,真是。。。所幸问题找到了,去掉那个库问题果然解决了。Java反射真是强大

不过,我在打log的时候惊奇的发现,THREAD_POOL_EXECUTOR在我手机上只开了一个线程,很奇怪,按理说不应该这样的。。。留到后面再看看是咋回事吧

在Application初始化的时候

MyExecutor executor = new MyExecutor();
    try {
      Field field = AsyncTask.class.getField("THREAD_POOL_EXECUTOR");
      field.setAccessible(true);
      field.set(null, executor);
    } catch (Exception e) {
      Log.e("MyAsyncTask","exception when using reflection");
    }

自己写的Executor

public static class MyExecutor extends ThreadPoolExecutor {

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
      private final AtomicInteger mCount = new AtomicInteger(1);

      public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
      }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

    public MyExecutor() {
      super(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
          sPoolWorkQueue, sThreadFactory);
      allowCoreThreadTimeOut(true);
    }

    @Override public void execute(Runnable command) {
      if (command != null) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        new Throwable().printStackTrace(pw);
        Log.d("MyAsyncTask", sw.toString());
      }
      super.execute(command);
    }
  }