我能够正确加载证书并可以访问我的服务器(宝贝步骤...)现在我的问题是参数(“ username = admin&password = admin”)未进入服务器(请求为作为null来)。这是我从here获得的Android代码(其中一些):
String host = "turbo";
int port = 8081;
String command = "get_status";
String user = "admin";
String password = "admin";
HttpsURLConnection connection = null;
try {
Certificate ca;
String keyStoreType;
KeyStore keyStore;
String tmfAlgorithm;
TrustManagerFactory tmf;
Scanner scanner;
boolean hasInput;
/**
* Set up certificate stuff first
*/
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream ins = myContext.getResources().openRawResource(
myContext.getResources().getIdentifier("server_crt", "raw",
myContext.getPackageName()));
BufferedInputStream caInput = new BufferedInputStream(ins);
ca = cf.generateCertificate(caInput);
caInput.close();
keyStoreType = KeyStore.getDefaultType();
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL(String.format("https://%s:%d/test/%s", host, port, command));
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(context.getSocketFactory());
connection.setReadTimeout(1500);
connection.setConnectTimeout(1500);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream os = new DataOutputStream(connection.getOutputStream());
os.writeBytes("username=admin&password=admin");
String b = getPostDataString(params);
os.flush();
os.close();
我不得不将Flask运行方法更改为host ='0.0.0.0',现在我与下面的Android代码建立了连接,但是我遇到了其他问题:在获取参数(用户名和密码)。
在服务器端,我收到一个错误,其中参数(用户名)为空。
我也尝试过这样做:
Map<String,Object> params = new LinkedHashMap<>();
params.put("username", user);
params.put("password", password);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
connection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
connection.setDoOutput(true);
connection.getOutputStream().write(postDataBytes);
connection.setReadTimeout(30000);
connection.setConnectTimeout(30000);
int responseCode = connection.getResponseCode();
但是responseCode是400,我在服务器上遇到相同的错误(用户名未定义) 有什么建议吗?
app.run(debug=server_debug, ssl_context=context, host='0.0.0.0', port=server_port)
我无法通过具有自签名证书的Android应用程序通过HTTPS连接。
我创建了create_key.cfg:
[req]
default_bits=2048
prompt=no
default_md=sha256
x509_extensions=v3_req
#req_extensions=req_ext
distinguished_name=dn
[dn]
C=US
ST=Florida
L=Satellite Beach
O=ThompCo, Inc
OU=turbo
emailAddress=Jordan@ThompCo.com
CN=turbo
[v3_req]
subjectAltName=@alt_names
[alt_names]
DNS.1=turbo
DNS.2=turbo.thompco.com
DNS.3=thompco.com
然后我运行了以下命令:
openssl req -x509 -nodes -days 730 -newkey rsa:2048 -keyout server.key -out server.crt -config create_key.cfg -sha256
openssl x509 -in server.crt -out server.pem -outform PEM
创建文件:
server.crt server.key server.pem
当我使用Chrome访问该网站时,我会获得正确的证书信息(显然,警告是该证书不安全)
当我运行测试python脚本(使用urllib2)时,一切正常。
我尝试过直卷发:
curl https://turbo:8081
但是我得到了这个错误:
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
我尝试按照建议的here将crt文件添加到/ usr / lib / ssl / certs,但这没有帮助(也许这是问题的根源吗?)
我正在Android中涉猎(请阅读“我不知道我在做什么”),并已经(在Google和世界各地许多优秀的开发人员的帮助下)编写了以下内容(请注意,我将server.pem放入了res / raw文件夹):
package com.thompco.test;
import android.content.Context;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Scanner;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
class DoCurl extends Thread {
Context myParentContext;
public DoCurl(Context context) {
myParentContext = context;
}
public void run() {
String host = "turbo";
int port = 8081;
HttpsURLConnection connection = null;
String command = "get_status";
String http = "https";
String user = "admin";
String password = "admin";
try {
Certificate ca;
String keyStoreType;
KeyStore keyStore;
String tmfAlgorithm;
TrustManagerFactory tmf;
SSLContext context;
URL url;
InputStream in;
Scanner scanner;
boolean hasInput;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream ins = myParentContext.getResources().openRawResource(
myParentContext.getResources().getIdentifier("server",
"raw", myParentContext.getPackageName()));
BufferedInputStream caInput = new BufferedInputStream(ins);
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
keyStoreType = KeyStore.getDefaultType();
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
url = new URL(String.format("%s://%s:%d/test/%s", http, host, port, command));
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(context.getSocketFactory());
connection.setRequestProperty("username", user);
connection.setRequestProperty("password", password);
connection.setReadTimeout(30000);
connection.setConnectTimeout(30000);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.connect();
if (connection.getResponseCode() == 200) {
// Success
// Further processing here
} else {
// Error handling code goes here
}
in = connection.getInputStream();
scanner = new Scanner(in);
scanner.useDelimiter("\\A");
hasInput = scanner.hasNext();
if (hasInput) {
String tmp = scanner.next();
}
} catch (Exception e) {
Exception blah = e;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
运行此方法时,它将引发java.security.cert.CertPathValidatorException:尝试连接时找不到证书路径的信任锚。
我的目标是能够部署此设备(当前正在运行Flask)并能够从本地网络上的Android手机访问它。如果可以的话,我不想安装真正可信的证书。
该服务器恰巧在Windows计算机上以python运行。我的卷曲测试效果很好,我知道那不是最好的方法,但是我现在只是在测试Android应用。
我返回了我的Python测试代码,并确认我已正确连接(请注意我正在使用适当的.crt文件),该文件应验证自签名证书的有效性:< / p>
def send_curl(command, host, port, data, use_ssh=True):
logger = get_logger()
logger.debug("host:{}, port:{}".format(host, port))
context = ssl.create_default_context()
context.load_verify_locations("../keys/server.crt")
url = '{}://{}:{}/test/{}'.format("https", host, port, command)
for k, v in data.items():
data[k] = str(v)
data = json.dumps(data)
logger.debug("URL is {}".format(url))
logger.debug("data is {}".format(data))
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
try:
rtn = urllib2.urlopen(req, context=context)
pp = pprint.PrettyPrinter()
pp.format = my_safe_repr
print "Success:" + str(rtn.code)
pp.pprint(data)
except urllib2.HTTPError as err:
print str(err) + ":"
print err.read()
data = None
return data
答案 0 :(得分:0)
您可以在Android应用上创建此类。
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HttpsTrustManager implements X509TrustManager {
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
private static TrustManager[] trustManagers;
public static void allowAllSSL() {
// HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
//
// @Override
// public boolean verify(String arg0, SSLSession arg1) {
// return true;
// }
// });
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
@Override
public void checkClientTrusted(
X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
}
并在HttpsTrustManager.allowAllSSL();
上使用OnCreate()
方法
答案 1 :(得分:0)
这是我可以解决几个问题的解决方案(安全地与自签名证书连接,向服务器传递json或从服务器接收json,让Flask服务器在所有接口上侦听)。希望这会帮助某人:
String host = "turbo";
int port = 8081;
String command = "get_status";
String user = "admin";
String password = "admin";
HttpsURLConnection connection = null;
try {
Certificate ca;
String keyStoreType;
KeyStore keyStore;
String tmfAlgorithm;
TrustManagerFactory tmf;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream ins = myContext.getResources().openRawResource(
myContext.getResources().getIdentifier("server_crt", "raw",
myContext.getPackageName()));
BufferedInputStream caInput = new BufferedInputStream(ins);
ca = cf.generateCertificate(caInput);
caInput.close();
keyStoreType = KeyStore.getDefaultType();
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL(String.format("https://%s:%d/test/%s", host, port, command));
JSONObject params = new JSONObject();
params.put("username", user);
params.put("password", password);
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(context.getSocketFactory());
connection.setReadTimeout(4500);
connection.setConnectTimeout(4500);
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoInput(true);
connection.setDoOutput(true);
OutputStreamWriter wr= new OutputStreamWriter(connection.getOutputStream());
wr.write(params.toString());
wr.flush();
wr.close();
switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_CREATED:
case HttpURLConnection.HTTP_OK:
BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();;
JSONObject jsonObj = new JSONObject(sb.toString());
}
} catch (Exception e) {
Exception blah = e;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
我必须更改Flask run()方法以包含参数:
host='0.0.0.0'
我创建了create_key.cfg:
[req]
default_bits=2048
prompt=no
default_md=sha256
x509_extensions=v3_req
#req_extensions=req_ext
distinguished_name=dn
[dn]
C=US
ST=Florida
L=Satellite Beach
O=ThompCo, Inc
OU=turbo
emailAddress=Jordan@ThompCo.com
CN=turbo
[v3_req]
subjectAltName=@alt_names
[alt_names]
DNS.1=turbo
DNS.2=turbo.thompco.com
DNS.3=thompco.com
然后我运行了以下命令:
openssl req -x509 -nodes -days 730 -newkey rsa:2048 -keyout server.key -out server.crt -config create_key.cfg -sha256
创建文件:
server.crt server.key