我正在尝试将我的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))
如何正确执行操作?
首选方法是,如果没有其他选项可以接受所有证书,则使用自签名证书来工作。
预先感谢:-)
答案 0 :(得分: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资源管理器中找到文件夹,然后将其放入文件夹中。
我希望您会发现它有用:-)