android用okhttp3连接自签名的https

android用okhttp3连接自签名的https

想在android中使用加密的https连接,但机构颁发的加密证书很贵?可以使用自签名的证书哦,零成本。android访问自签名的https会报错,通常做法是闭着眼睛,直接忽略掉证书验证。如果可以简单忽略,那何必使用加密https呢;如果可以简单忽略,那安全性如何保证呢?这里有不忽略的方法。

准备工作

  1. 生成一个自签名证书(待续)
  2. 使用这个自签名证书,提供https服务(待续)
  3. 使用这个自签名证书,生成hello.cer证书文件,供android上使用

生成自签名证书

openssl genrsa -des3 -out server.key.en 2048
openssl rsa -in server.key.en -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
openssl x509 -in server.crt -out server.cer -outform der
  1. 生成一个非对称加密算法rsa的密钥文件(server.key.en),包含密钥对,公钥和私钥。
  2. 生成密钥文件必须输入密码,所以密钥文件(server.key.en)有密码包含,第二步删除这个密码。
  3. 在密钥文件的基础上,生成证书请求文件(server.csr)。证书请求文件需要得到CA组织的签名认证后,才是证书。
  4. CA组织的签名认证是收费服务,所以我们选择自签名,自己给自己签名。把自己当作是CA组织,用自己的密钥文件,对自己的证书请求文件签名。自己给自己认证。文件(server.crt)就是自签名证书。
  5. 自签名证书(server.crt)因为格式的原因,不能在android中直接使用。把它转换为android接受的cer格式。

在android上的处理

  1. 思路。因为自签名证书不在android信任的KeyStore中,所以就报错。现在使用自签名的证书hello.cer,生成一个新的KeyStore,把它作为受信任的KeyStore提供给okhhtp3。在https请求时,okhhtp3用我们自己受信任的KeyStore去验证服务器,就保证了安全性。
  2. java实现:
public static String httpsGet(Context context, String url) {
		String rst = null;

		SSLSocketFactory sslSocketFactory = null;
		X509TrustManager trustManager = null;
		HostnameVerifier hostnameVerifier = null;
		InputStream is = null;
		try {
			is = context.getAssets().open("hello.cer");
			Certificate certificate = CertificateFactory.getInstance("X.509")
					.generateCertificate(is);
			if (is != null) {
				is.close();
			}
			KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
			keyStore.load(null);
			keyStore.setCertificateEntry("ca", certificate);

			TrustManagerFactory trustManagerFactory = TrustManagerFactory
					.getInstance(TrustManagerFactory.getDefaultAlgorithm());
			trustManagerFactory.init(keyStore);
			TrustManager[] trustManagers = trustManagerFactory
					.getTrustManagers();
			if (trustManagers.length != 1
					|| !(trustManagers[0] instanceof X509TrustManager)) {
				throw new IllegalStateException(
						"Unexpected default trust managers:"
								+ Arrays.toString(trustManagers));
			}
			trustManager = (X509TrustManager) trustManagers[0];

			hostnameVerifier = new HostnameVerifier() {
				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}
			};

			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new TrustManager[] { trustManager }, null);
			sslSocketFactory = sslContext.getSocketFactory();
		} catch (CertificateException e1) {
			e1.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}

		Request request = new Request.Builder().url(url).build();
		OkHttpClient okHttpClient = new OkHttpClient.Builder()
				.hostnameVerifier(hostnameVerifier)
				.sslSocketFactory(sslSocketFactory, trustManager).build();
		try {
			Response response = okHttpClient.newCall(request).execute();
			if (response.isSuccessful()) {
				rst = response.body().string();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return rst;
	}

转载于:https://my.oschina.net/kyle960/blog/1811031

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用程序中使用 ArcGIS SDK 并配置 HTTPS,请按照以下步骤操作: 1. 在项目级别的 build.gradle 文件中添加以下依赖项: ``` dependencies { implementation 'com.esri.arcgisruntime:arcgis-android:100.9.0' implementation 'com.squareup.okhttp3:okhttp:4.5.0' } ``` 2. 在 AndroidManifest.xml 文件中添加以下权限和组件: ``` <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application ... <activity android:name="com.esri.arcgisruntime.mapping.view.MapView" android:configChanges="keyboardHidden|orientation|screenSize" /> <meta-data android:name="com.esri.arcgisruntime.API_KEY" android:value="YOUR_API_KEY" /> </application> ``` 3. 在您的项目中创建一个名为 `MySSLSocketFactory` 的类,以允许使用自签名证书连接HTTPS 站点: ``` public class MySSLSocketFactory { public static SSLSocketFactory getSocketFactory(InputStream caCertFile) { try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); Certificate ca; try { ca = cf.generateCertificate(caCertFile); } finally { caCertFile.close(); } KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); return sslContext.getSocketFactory(); } catch (Exception ex) { Log.e("MySSLSocketFactory", "Error while setting SSLSocketFactory", ex); return null; } } } ``` 4. 在您的代码中使用 `MySSLSocketFactory` 和 `OkHttpClient` 实现 HTTPS 连接: ``` InputStream caCertFile = getResources().openRawResource(R.raw.ca_cert); SSLSocketFactory socketFactory = MySSLSocketFactory.getSocketFactory(caCertFile); OkHttpClient.Builder builder = new OkHttpClient.Builder() .sslSocketFactory(socketFactory, (X509TrustManager) trustAllCerts[0]) .hostnameVerifier((hostname, session) -> true); ArcGISMap map = new ArcGISMap(Basemap.Type.TOPOGRAPHIC, 34.056295, -117.195800, 10); MapView mapView = new MapView(this); mapView.setMap(map); ArcGISMapImageLayer mapImageLayer = new ArcGISMapImageLayer(URL_TO_HTTPS_SERVICE); mapImageLayer.setCredential(new UserCredential("USERNAME", "PASSWORD")); mapView.getMap().getOperationalLayers().add(mapImageLayer); ``` 请注意,您需要将 `URL_TO_HTTPS_SERVICE` 替换为您要连接HTTPS 服务的 URL,以及将 `USERNAME` 和 `PASSWORD` 替换为您的凭据。另外,请确保您已在 ArcGIS 开发人员网站上注册并获取了您的 API 密钥,并将其替换为 `YOUR_API_KEY`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值