Android动态加载基础 ClassLoader工作机制

类加载器ClassLoader 早期使用过Eclipse等Java编写的软件的同学可能比较熟悉,Eclipse可以加载许多第三方的插件(或者叫扩展),这就是动态加载。这些插件大多是一些Jar包,而使用插件其实就是动态加载Jar包里的Class进行工作。这其实非常好理解,Java代码都是写在Class里面的,程序运行在虚拟机上时,虚拟机需要把需要的Class加载进来才能创建实例对象并工作,而完成这一个加载工作的角色就是ClassLoader。 对于Java程序来说,编写程序就是编写类,运行程序也就是运行类(编译得到的class文件),其中起到关键作用的就是类加载器ClassLoader。 Android的Dalvik/ART虚拟机如同标准JAVA的JVM虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。因此,我们可以利用这一点,在程序运行时手动加载Class,从而达到代码动态加载可执行文件的目的。Android的Dalvik/ART虚拟机虽然与标准Java的JVM虚拟机不一样,ClassLoader具体的加载细节不一样,但是工作机制是类似的,也就是说在Android中同样可以采用类似的动态加载插件的功能,只是在Android应用中动态加载一个插件的工作要比Eclipse加载一个插件复杂许多(这点后面在解释说明)。 有几个ClassLoader实例? 动态加载的基础是ClassLoader,从名字也可以看出,ClassLoader就是专门用来处理类加载工作的,所以这货也叫类加载器,而且一个运行中的APP 不仅只有一个类加载器。 其实,在Android系统启动的时候会创建一个Boot类型的ClassLoader实例,用于加载一些系统Framework层级需要的类,我们的Android应用里也需要用到一些系统的类,所以APP启动的时候也会把这个Boot类型的ClassLoader传进来。 此外,APP也有自己的类,这些类保存在APK的dex文件里面,所以APP启动的时候,也会创建一个自己的ClassLoader实例,用于加载自己dex文件中的类。下面我们在项目里验证看看 ` <span class="hljs-annotation">@Override</span> <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{ <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); ClassLoader classLoader = getClassLoader(); <span class="hljs-keyword">if</span> (classLoader != <span class="hljs-keyword">null</span>){ Log.i(TAG, <span class="hljs-string">"[onCreate] classLoader "</span> + i + <span class="hljs-string">" : "</span> + classLoader.toString()); <span class="hljs-keyword">while</span> (classLoader.getParent()!=<span class="hljs-keyword">null</span>){ classLoader = classLoader.getParent(); Log.i(TAG,<span class="hljs-string">"[onCreate] classLoader "</span> + i + <span class="hljs-string">" : "</span> + classLoader.toString()); } } }` 输出结果为 ...

2017年4月25日 · 7 分钟 · 天边的星星

深入浅出ClassLoader ,超详细java中的ClassLoader详解

你真的了解ClassLoader吗? 这篇文章翻译自zeroturnaround.com的 Do You Really Get Classloaders? ,融入和补充了笔者的一些实践、经验和样例。本文的例子比原文更加具有实际意义,文字内容也更充沛一些,非常感谢作者 Jevgeni Kabanov 能够共享如此优秀的文档。 1. 为什么你需要了解和敬畏ClassLoader ClassLoader在Java语言中占据了核心地位,Java应用服务器,OSGi,以及大量的网络框架,它们大多数都用到了ClassLoader。如果在使用过程中出现了类加载错误,你能解决它吗? 我们将从JVM和开发者两个角度讲述ClassLoader,将会选择一些典型的案例,然后演示如何解决它们。NoClassDefFoundError,LinkageError等很多错误都会有特定的表征,我们分析每个例子,然后进行解决。 2. 进入ClassLoader 每个ClassLoader对象都是一个java.lang.ClassLoader的实例。每个Class对象都被这些ClassLoader对象所加载,通过继承java.lang.ClassLoader可以扩展出自定义ClassLoader,并使用这些自定义的ClassLoader对类进行加载。 先大体了解一下ClassLoader的API: `01` <td class="content"> `package` `java.lang;` </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `02` </td> <td class="content"> </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `03` </td> <td class="content"> `public` `abstract` `class` `ClassLoader {` </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `04` </td> <td class="content"> ` ``public` `Class loadClass(String name);` </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `05` </td> <td class="content"> </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `06` </td> <td class="content"> ` ``protected` `Class defineClass(``byte``[] b);` </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `07` </td> <td class="content"> </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `08` </td> <td class="content"> ` ``public` `URL getResource(String name);` </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `09` </td> <td class="content"> </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `10` </td> <td class="content"> ` ``public` `Enumeration getResources(String name);` </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `11` </td> <td class="content"> </td> </tr> </table> </div> <div class="line alt2"> <table> <tr> <td class="number"> `12` </td> <td class="content"> ` ``public` `ClassLoader getParent();` </td> </tr> </table> </div> <div class="line alt1"> <table> <tr> <td class="number"> `13` </td> <td class="content"> `}` </td> </tr> </table> </div> 最重要的是ClassLoader的<span lang="EN-US">loadClass</span>方法,它接受一个全类名,然后返回一个Class类型的实例。 ...

2017年4月25日 · 39 分钟 · 天边的星星

Nginx单IP地址配置多个SSL证书

默认情况下,Nginx一个IP地址仅支持一个SSL证书,需要多个IP地址才能配置多个SSL证书,在公网IP地址有限的情况下,可以使用TLS Server Name Indication extension(SNI, RFC 6066),它允许浏览器在SSL握手的时候发送请求的server name,也就是 Host,这样 Nginx 就能找到对应server 的SSL配置。 配置步骤如下: 1、检查Nginx是否支持TLS nginx -V … TLS SNI support enabled … nginx -V … TLS SNI support enabled … 2、如果出现TLS SNI support disable,就得升级openssl版本,并且重新编译nginx。 具体步骤如下: 首先下载openssl(建议下载1.0.1h版本) #wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz 下载Nginx #wget http://nginx.org/download/nginx-1.9.9.tar.gz 解压openssl #tar -zxvf openssl-1.0.1h.tar.gz 解压nginx,并编译 #tar -zxvf nginx-1.9.9.tar.gz #cd nginx-1.9.9 #make && make install #检查Nginx版本信息 #/usr/local/nginx/sbin/nginx -V nginx version: nginx/1.9.9 built by gcc 4.1.2 20080704 (Red Hat 4.1.2-55) built with OpenSSL 1.0.1h 5 Jun 2014 TLS SNI support enabled ...

2017年1月11日 · 1 分钟 · 天边的星星

Android插件化开发之用DexClassLoader加载未安装的APK来实现app切换背景皮肤

第一步、先制做一个有我们需要的图片资源的APK 如下图,这里有个about_log.png,我们需要生成apk文件。 生成的apk文件如果你不到项目的文件夹里面去取apk,想通过命令放到手机里面去可以快速用下面命令 1)、在手机里面通过包名找到apk路径,一定不要忘记有 -f - adb shell pm list package -f | grep com.example.testclassloader 得到如下结果 - package:/data/app/com.example.testclassloader-2/<span class="attribute">base.apk</span>=<span class="attribute-value">com</span>.example.testclassloader 2)、把base.apk拉到本地然后改名字,命令如下 - adb shell pull /data/app/com.example.testclassloader-2/base.apk testClassLoader.apk 3)、把testClassLoader.apk放到手机里面去,命令如下 - adb shell push testClassLoader.apk /sdcard/ 4)、去手机文件管理器里面找看是否有testClassLoader.apk文件 ...

2016年11月23日 · 5 分钟 · 天边的星星

我的Android进阶之旅——>Android关于HttpsURLConnection一个忽略Https证书是否正确的Https请求工具类

下面是一个android HttpsURLConnection忽略Https证书是否正确的Https请求工具类,不需要验证服务器端证书是否正确 import Java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; import java.util.Map.Entry; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; /** * 忽略Https证书是否正确的Https Post请求工具类 * &lt;p/&gt; * created by OuyangPeng on 2016/1/17. */ public class HttpUtil { private static final String DEFAULT_CHARSET = "UTF-8"; // 默认字符集 private static final String _GET = "GET"; // GET private static final String _POST = "POST";// POST /** * 初始化http请求参数 */ private static HttpURLConnection initHttp(String url, String method, Map&lt;String, String&gt; headers) throws IOException { URL _url = new URL(url); HttpURLConnection http = (HttpURLConnection) _url.openConnection(); // 连接超时 http.setConnectTimeout(25000); // 读取超时 --服务器响应比较慢,增大时间 http.setReadTimeout(25000); http.setRequestMethod(method); http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); http.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) [chrome](http://www.07net01.com/tags-chrome-0.html)/33.0.1750.146 Safari/537.36"); if (null != headers && !headers.isEmpty()) { for (Entry&lt;String, String&gt; entry : headers.entrySet()) { http.setRequestProperty(entry.getKey(), entry.getValue()); } } http.setDoOutput(true); http.setDoInput(true); http.connect(); return http; } /** * 初始化http请求参数 */ private static HttpsURLConnection initHttps(String url, String method, Map&lt;String, String&gt; headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { TrustManager[] tm = {new MyX509TrustManager()}; SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL _url = new URL(url); HttpsURLConnection http = (HttpsURLConnection) _url.openConnection(); // 设置域名校验 http.setHostnameVerifier(new TrustAnyHostnameVerifier()); http.setSSLSocketFactory(ssf); // 连接超时 http.setConnectTimeout(25000); // 读取超时 --服务器响应比较慢,增大时间 http.setReadTimeout(25000); http.setRequestMethod(method); http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); http.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"); if (null != headers && !headers.isEmpty()) { for (Entry&lt;String, String&gt; entry : headers.entrySet()) { http.setRequestProperty(entry.getKey(), entry.getValue()); } } http.setDoOutput(true); http.setDoInput(true); http.connect(); return http; } /** * get请求 */ public static String get(String url, Map&lt;String, String&gt; params, Map&lt;String, String&gt; headers) { StringBuffer bufferRes = null; try { HttpURLConnection http = null; if (isHttps(url)) { http = initHttps(initParams(url, params), _GET, headers); } else { http = initHttp(initParams(url, params), _GET, headers); } InputStream in = http.getInputStream(); BufferedReader read = new BufferedReader(new InputStreamReader(in, DEFAULT_CHARSET)); String valueString = null; bufferRes = new StringBuffer(); while ((valueString = read.readLine()) != null) { bufferRes.append(valueString); } in.close(); if (http != null) { http.disconnect();// 关闭连接 } return bufferRes.toString(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * get请求 */ public static String get(String url) { return get(url, null); } /** * get请求 */ public static String get(String url, Map&lt;String, String&gt; params) { return get(url, params, null); } /** * post请求 */ public static String post(String url, String params, Map&lt;String, String&gt; headers) { StringBuffer bufferRes = null; try { HttpURLConnection http = null; if (isHttps(url)) { http = initHttps(url, _POST, headers); } else { http = initHttp(url, _POST, headers); } OutputStream out = http.getOutputStream(); out.write(params.getBytes(DEFAULT_CHARSET)); out.flush(); out.close(); InputStream in = http.getInputStream(); BufferedReader read = new BufferedReader(new InputStreamReader(in, DEFAULT_CHARSET)); String valueString = null; bufferRes = new StringBuffer(); while ((valueString = read.readLine()) != null) { bufferRes.append(valueString); } in.close(); if (http != null) { http.disconnect();// 关闭连接 } return bufferRes.toString(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * post请求 */ public static String post(String url, Map&lt;String, String&gt; params) { return post(url, map2Url(params), null); } /** * post请求 */ public static String post(String url, Map&lt;String, String&gt; params, Map&lt;String, String&gt; headers) { return post(url, map2Url(params), headers); } /** * 初始化参数 */ public static String initParams(String url, Map&lt;String, String&gt; params) { if (null == params || params.isEmpty()) { return url; } StringBuilder sb = new StringBuilder(url); if (url.indexOf("?") == -1) { sb.append("?"); } sb.append(map2Url(params)); return sb.toString(); } /** * map转url参数 */ public static String map2Url(Map&lt;String, String&gt; paramToMap) { if (null == paramToMap || paramToMap.isEmpty()) { return null; } StringBuffer url = new StringBuffer(); boolean isfist = true; for (Entry&lt;String, String&gt; entry : paramToMap.entrySet()) { if (isfist) { isfist = false; } else { url.append("&"); } url.append(entry.getKey()).append("="); String value = http://blog.csdn.net/ouyang_peng/article/details/entry.getValue(); if (null == value || "".equals(value.trim())) { try { url.append(URLEncoder.encode(value, DEFAULT_CHARSET)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } return url.toString(); } /** * 检测是否https */ private static boolean isHttps(String url) { return url.startsWith("https"); } /** * 不进行主机名确认 */ private static class TrustAnyHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } } /** * 信任所有主机 对于任何证书都不做SSL检测 * 安全验证机制,而Android采用的是X509验证 */ private static class MyX509TrustManager implements X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } } } ...

2016年8月10日 · 4 分钟 · 天边的星星

charles工具抓包教程(http跟https)

1.下载charles 可以去charles官网下载,下载地址:http://www.charlesproxy.com/download/ 根据自己的操作系统下载对应的版本,然后进行安装,然后打开charles工具 2.设置代理(记住手机跟电脑要在同一个网络,用的同一个路由器) 1).查看默认端口 Proxy->Proxy Settings 在这个页面会看到HTTP Proxy的默认端口是8888 我们不需要修改,只需要知道有这个值就行 2).查看当前电脑的ip 例如我这里的是:192.168.9.129 3).知道了默认端口跟ip地址,我们就可以手机上设置代理了。设置步骤我录制了gif动画。(我用的是genymotion模拟器,真机也是一样的) 完成了以上两个步骤就可以抓到http请求的数据了,效果图如下: 接下来讲解如何抓取https协议的包,如果你没有这个需求,请不要继续浏览下面的内容 3.设置charles ssl代理 Proxy->SSL Proxy Settings 弹出一个ssl代理设置界面 1).Enable SSL Proxying复选框打上勾 2).添加你想要的设置代理的域名,端口默认443 设置过后效果图如下: 4.手机下载ssl证书 1).Help->SSL Proxying ->Install Charles Root Certificate on a Mobile Device or Remote Browser… 会弹出一个提示框,如下显示: 浏览器输入这个地址即可下载证书,记住要用Android自带的浏览器. 地址是:http://charlesproxy.com/getssl 扫一扫二维码安装ssl 2).然后按照他的提示安装证书即可. 做完第三步跟第四步就可以抓包https数据了.如果还有问题请留言。。。下面是我抓包截图。 方法二 HTTP包: 1.安装抓包工具 Charles , 到官网http://www.charlesproxy.com/可下载到最新版本 2.用安装了charles的电脑,代理待抓包anroid手机的网络连接: 首先查看pc的网络IP地址;打开手机设置,进入当前wifi连接,设置代理为手动,将服务器填为上一步中获得的IP,端口默认为8888(在charles的proxy setting中可以改这个端口号)。这时Charles弹出确认框,点击Allow按钮即可 3.中文乱码问题解决 在charles的content/info.plist 中 的vmoption 添加-Dfile.encoding=UTF-8 HTTPS抓包: 下载Charles证书http://www.charlesproxy.com/ssl.zip,解压后导入到手机中,然后设置->安全->凭据存储->从存储设备安装,选中证书。 在Charles的工具栏上点击设置按钮,选择Proxy Settings;切换到SSL选项卡,选中Enable SSL Proxying,选项卡的Locations表单可以填写要抓包的域名和端口,点击Add按钮,在弹出的表单中Host填写域名,比如填api.instagram.com,Port填443。默认的..表示应用于所有地址

2016年7月19日 · 1 分钟 · 天边的星星

oschina-app源码分析-提醒标签BadgeView使用方法https://github.com/chenupt/BezierDemo

看过oschina-app的数字提醒标签BadgeView的使用过程,才发现以前项目中的实现逻辑有问题。以前待的项目组没个牛人,从我干第一个项目就我负责开发设计和管理,可想而知,顶多也就实现功能交工。说到底就是经验不足,所以有时间还是多看看别人的代码。本来是想主要讲oschina-app里面提醒标签的实现逻辑,但我觉得标签控件BadgeView有必要说下。 BadgeView是一个开源的ui项目,其实就一个ui工具类,BadgeView是对TextView的重写,他的代码就不贴了,可以到git上下最新的吧:https://github.com/jgilfelt/android-viewbadger 在这里主要说下他的用法,它可以设置标签的背景、颜色、位置、动画、文字等,对一般的需求足以满足了,先看下git上demo的效果: 默认属性标签代码: **[java]** [view plain](http://blog.csdn.net/xiangxue336/article/details/21073571#)[copy](http://blog.csdn.net/xiangxue336/article/details/21073571#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/230977)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/230977/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="comment">// *** default badge ***</span> - - View target = findViewById(R.id.default_target); - BadgeView badge = <span class="keyword">new</span> BadgeView(<span class="keyword">this</span>, target); - badge.setText(<span class="string">&#8220;1&#8221;</span>); - badge.show(); 默认是显示在右上角,红色的背景白色字体,这些个默认属性是可以在BadgeView里面设置的。 设置position代码: **[java]** [view plain](http://blog.csdn.net/xiangxue336/article/details/21073571#)[copy](http://blog.csdn.net/xiangxue336/article/details/21073571#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/230977)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/230977/fork) <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> </div> - <span class="comment">// *** set position ***</span> - - btnPosition = (Button) findViewById(R.id.position_target); - badge1 = <span class="keyword">new</span> BadgeView(<span class="keyword">this</span>, btnPosition); - badge1.setText(<span class="string">&#8220;12&#8221;</span>); - badge1.setBadgePosition(BadgeView.POSITION_CENTER); - btnPosition.setOnClickListener(<span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) { - badge1.toggle(); - } - }); toggle方法是控制标签的现实和隐藏的。 ...

2015年3月24日 · 2 分钟 · 天边的星星

Android HTTPS详解

前言 最近有一个跟Https相关的问题需要解决,因此花时间学习了一下Android平台Https的使用,同时也看了一些Https的原理,这里分享一下学习心得。 HTTPS原理 HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的。HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议。所以,研究HTTPS协议原理,最终其实就是研究SSL/TLS协议。 SSL/TLS协议作用 不使用SSL/TLS的HTTP通信,就是不加密的通信,所有的信息明文传播,带来了三大风险: 窃听风险:第三方可以获知通信内容。 篡改风险:第三方可以修改通知内容。 冒充风险:第三方可以冒充他人身份参与通信。 SSL/TLS协议是为了解决这三大风险而设计的,希望达到: 所有信息都是加密传输,第三方无法窃听。 具有校验机制,一旦被篡改,通信双方都会立刻发现。 配备身份证书,防止身份被冒充。 基本的运行过程 SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。但是这里需要了解两个问题的解决方案。 如何保证公钥不被篡改? 解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。 公钥加密计算量太大,如何减少耗用的时间? 解决方法:每一次对话(session),客户端和服务器端都生成一个“对话密钥”(session key),用它来加密信息。由于“对话密钥”是对称加密,所以运算速度非常快,而服务器公钥只用于加密“对话密钥”本身,这样就减少了加密运算的消耗时间。 因此,SSL/TLS协议的基本过程是这样的: 客户端向服务器端索要并验证公钥。 双方协商生成“对话密钥”。 双方采用“对话密钥”进行加密通信。 上面过程的前两布,又称为“握手阶段”。 握手阶段的详细过程 “握手阶段”涉及四次通信,需要注意的是,“握手阶段”的所有通信都是明文的。 客户端发出请求(ClientHello) 首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。在这一步中,客户端主要向服务器提供以下信息: 支持的协议版本,比如TLS 1.0版 一个客户端生成的随机数,稍后用于生成“对话密钥”。 支持的加密方法,比如RSA公钥加密。 支持的压缩方法。 这里需要注意的是,客户端发送的信息之中不包括服务器的域名。也就是说,理论上服务器只能包含一个网站,否则会分不清应用向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。 服务器回应(ServerHello) 服务器收到客户端请求后,向客户端发出回应,这叫做ServerHello。服务器的回应包含以下内容: 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。 一个服务器生成的随机数,稍后用于生成“对话密钥”。 确认使用的加密方法,比如RSA公钥加密。 服务器证书。 除了上面这些信息,如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供“客户端证书”。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。 客户端回应 客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁发,或者证书中的域名与实际域名不一致,或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。 如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项消息。 一个随机数。该随机数用服务器公钥加密,防止被窃听。 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项通常也是前面发送的所有内容的hash值,用来供服务器校验。 上面第一项随机数,是整个握手阶段出现的第三个随机数,又称“pre-master key”。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把“会话密钥”。 服务器的最后回应 服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的“会话密钥”。然后,向客户端最后发送下面信息。 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发生的所有内容的hash值,用来供客户端校验。 握手结束 至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用“会话密钥”加密内容。 服务器基于Nginx搭建HTTPS虚拟站点 之前一篇文章详细介绍了在服务器端如何生成SSL证书,并基于Nginx搭建HTTPS服务器,链接:Nginx搭建HTTPS服务器 Android实现HTTPS通信 由于各种原因吧,这里使用HttpClicent类讲解一下Android如何建立HTTPS连接。代码demo如下。 MainActivity.java ``` package com.example.photocrop; import java.io.BufferedReader; import java.io.InputStreamReader; ...

2014年12月15日 · 12 分钟 · 天边的星星

file_get_contents()获取https出现这个错误Unable to find the wrapper “https” – did

例如你的原路径是 http://localhost/test/index.php/index/add那么现在的地址是 http://localhost/test/index/add如何去掉index.php呢?1.httpd.conf配置文件中加载了mod_rewrite.so模块 //在APACHE里面去配置#LoadModule rewrite_module modules/mod_rewrite.so把前面的警号去掉2.AllowOverride None 讲None改为 All //在APACHE里面去配置 (注意其他地方的AllowOverride也统统设置为ALL)<Directory “D:/server/apache/cgi-bin”>AllowOverride none 改 AllowOverride ALLOptions NoneOrder allow,denyAllow from all3.确保URL_MODEL设置为2,在项目的配置文件里写return Array( ‘URL_MODEL’ => ‘2’,);4 .htaccess文件必须放到跟目录下这个文件里面加:RewriteEngine onRewriteCond %{REQUEST_FILENAME} !-dRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^(.*)index.php/1 [QSA,PT,L]补充:在windows下不能建立以点开头的文件,你可以先随便建立一个文件然后在DOS在操作 rename xxxx.xxxx .htaccess ...

2014年9月15日 · 1 分钟 · 天边的星星