![](/img/trans.png)
[英]Spring Boot - client server REST API with self-signed certificate
[英]Client can't connect to REST API using self-signed certificate
我正在嘗試將我的Android客戶端連接到TOMCAT REST API。 只要使用HTTP,一切正常。 不幸的是,必須實施HTTPS。
在服務器端HTTPS實現服務器看起來正常之后(服務器正在使用自簽名證書。使用JAVA KEYTOOL創建)。
不幸的是,由於某些原因,我無法連接Android客戶端。
最初的錯誤是:“找不到證書路徑的信任錨”。 我嘗試使用Android Developer指南,但是使用“ AsyncTask”訪問.crt / cer文件時遇到問題。 因此,我決定暫時可以使用“ ALLOW_ALL_HOSTNAME_VERIFIER”。 HTTPS CLIENT類如下所示:
(注釋部分為HTTP版本)
import android.util.Base64;
import android.os.Build;
import android.annotation.TargetApi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;
import android.os.AsyncTask;
import android.util.Log;
public class UrlUtil extends AsyncTask<String, Void, String> {
@TargetApi(Build.VERSION_CODES.O_MR1)
@Override
protected String doInBackground(String... strings) {
StringBuilder jsonResult = new StringBuilder();
String message = null;
try {
//setup SSL
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
String cred = "xxxx:yyyy";
String encoding = Base64.encodeToString(cred.getBytes(), Base64.DEFAULT);
// Example send http request
HttpPost httpPost = new HttpPost(strings[0]);
httpPost.setHeader("Authorization", "Basic " + encoding);
HttpResponse response = httpClient.execute(httpPost);
InputStream is = response.getEntity().getContent(); //outputs an inputstream
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
Log.d("httpstest",sb.toString());
return sb.toString();
} catch (IOException e) { }
return null;
// try {
// URL url = new URL(strings[0]);
//
// Authenticator.setDefault(new Authenticator() {
// protected PasswordAuthentication getPasswordAuthentication() {
// return new PasswordAuthentication("user", "userPass".toCharArray());
// }
// });
// HttpURLConnection connection = (HttpURLConnection) new URL(url.toString()).openConnection();
// connection.setUseCaches(false);
// connection.connect();
// InputStream inputStream = connection.getInputStream();
// InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
// BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// message = org.apache.commons.io.IOUtils.toString(bufferedReader);
//
// } catch (MalformedURLException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
//
//
// } catch (Exception e) { }
//
// return message;
}
}
錯誤信息:
07/09 18:27:29: Launching app
$ adb install-multiple -r -t -p org.pilat.eko_raporty20 C:\Users\Pilat\Desktop\AndroidStudioProjects\ekoraporty20\app\build\intermediates\split-apk\debug\slices\slice_9.apk
Split APKs installed in 2 s 675 ms
$ adb shell am start -n "org.pilat.eko_raporty20/org.pilat.eko_raporty20.activity.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Client not ready yet..Waiting for process to come online
Connected to process 944 on device lenovo-lenovo_p2a42-ZY223TJMN2
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/LenovoAppIconTheme: ExtraResources;cleanCachedIcon;clear cache..
W/ActivityThread: Application org.pilat.eko_raporty20 can be debugged on port 8100...
W/System: ClassLoader referenced unknown path: /data/app/org.pilat.eko_raporty20-1/lib/arm64
I/InstantRun: starting instant run server: is main process
I/Typeface: setThemeFont(): sThemeFontPath = ,fontPath =
W/Typeface: setThemeFont(): FontPath Not Changed!
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
V/BoostFramework: mAcquireFunc method = public int com.qualcomm.qti.Performance.perfLockAcquire(int,int[])
V/BoostFramework: mReleaseFunc method = public int com.qualcomm.qti.Performance.perfLockRelease()
mAcquireTouchFunc method = public int com.qualcomm.qti.Performance.perfLockAcquireTouch(android.view.MotionEvent,android.util.DisplayMetrics,int,int[])
mIOPStart method = public int com.qualcomm.qti.Performance.perfIOPrefetchStart(int,java.lang.String)
mIOPStop method = public int com.qualcomm.qti.Performance.perfIOPrefetchStop()
V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@e5acceb
BoostFramework() : mPerf = com.qualcomm.qti.Performance@fdb0a48
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
I/DpmTcmClient: RegisterTcmMonitor from: org.apache.http.impl.conn.TcmIdleTimerMonitor
I/System.out: [socket][0] connection /"ip":"port";LocalPort=-1(0)
I/System.out: [socket][/100.82.169.168:35907] connected
I/System.out: close [socket][/100.82.169.168:35907]
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.pilat.eko_raporty20, PID: 944
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.pilat.eko_raporty20/org.pilat.eko_raporty20.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toString()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2659)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2720)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6111)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toString()' on a null object reference
at org.pilat.eko_raporty20.activity.MainActivity.onCreate(MainActivity.java:126)
at android.app.Activity.performCreate(Activity.java:6734)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2612)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2720)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6111)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Application terminated.
為什么我沒有從服務器獲取數據?
(我不明白:I / System.out:[socket] [0]連接/“ ip”:“端口”; LocalPort = -1(0))
如何正確地做呢?
如果沒有其他選擇可以接受所有證書,則首選選項是使其使用自簽名證書來工作。
提前致謝 :-)
經過兩天的互聯網搜索並嘗試了許多選項的結果是使用Android Developer選項: https : //developer.android.com/training/articles/security-ssl比起添加證書文件,您將遇到問題。 Android將看不到它。 您可以通過將新的構造函數添加到AsyncTask類來添加證書。 它看起來應該像這樣:
Public class UrlUtil extends AsyncTask<String, String, String> {
private Context context;
public UrlUtil (Context myContext) {
this.context = myContext;
}
public UrlUtil () {};
@TargetApi(Build.VERSION_CODES.O_MR1)
@Override
protected String doInBackground(String... params) {...}
...}
您可以像這樣執行AsyncTask:
new UrlUtil(this).execute("https://myserver:myport/restofpath").get()
其中“ this”是ACTIVITY上下文。
證書文件應放在ASSETS文件夾中。 如果您的項目中沒有一個,最簡單的添加方法是右鍵單擊項目的“新建” /“文件夾” /“資產文件夾”。 要將文件添加到“資產文件夾”,您不能簡單地使用“拖放”。 您必須在OS資源管理器中找到文件夾並將其放入該文件夾中。
我希望您會發現它有用:-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.