[英]How to make a server request call from android secure like google api with sha1?
我正在制作一個始終調用服務器以加載數據(JSON數據)的應用程序。 像google api一樣,我如何確保POST請求是否來自我的android應用程序。 如何確保?
我總是將POST請求發送到php服務器的代碼如下
下面的代碼發送了諸如電話和密碼之類的數據來登錄,但是如果有人從我的android應用程序中復制並在他們的應用程序中使用過。 那么服務器將被黑客入侵。 如何防止它僅接受來自我的android應用程序的POST請求,而不接受任何其他來源的請求。
StringRequest stringRequest = new StringRequest(Request.Method.POST, REQ_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(HomeActivity.this, "" + response , Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
String message = null;
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
message=("Network Timeout Error");}
else if (error instanceof AuthFailureError) {
message=("Authentication Failure");}
else if (error instanceof ServerError) {
message=("Server Error");}
else if (error instanceof NetworkError) {
message=("Network Error");}
else if (error instanceof ParseError) {
message=("Network Timeout Error");}
error.printStackTrace();
Toast.makeText(HomeActivity.this, "" + message , Toast.LENGTH_LONG).show();
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("reqtype", "login");
params.put("phone", phone);
params.put("pass", password);
return params;
}
};
int socketTimeout = 15000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequest.setRetryPolicy(policy);
ServerRequest.getInstance(HomeActivity.this).addtoRequestQue(stringRequest);
因此需要首先學習適用於Android的SSL,並需要在服務器端創建SSL證書。
概念
在典型的SSL使用場景中,服務器配置有包含公鑰和匹配私鑰的證書。 作為SSL客戶端和服務器之間握手的一部分,服務器通過使用公共密鑰密碼術簽名其證書來證明它具有私有密鑰。
以下示例將使這些概念更加具體。 在下面命令行的摘錄中,openssl工具的s_client命令查看Wikipedia的服務器證書信息。 它指定端口443,因為這是HTTPS的默認端口。 該命令將openssl s_client的輸出發送到openssl x509,后者根據X.509標准格式化有關證書的信息。 具體來說,該命令要求提供包含服務器名稱信息的主題和標識CA的頒發者。
$ openssl s_client -connect wikipedia.org:443 | openssl x509 -noout -subject -issuer
subject= /serialNumber=sOrr2rKpMVP70Z6E9BT5reY008SJEdYv/C=US/O=*.wikipedia.org/OU=GT03314600/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - RapidSSL(R)/CN=*.wikipedia.org
issuer= /C=US/O=GeoTrust, Inc./CN=RapidSSL CA
不,您不需要像下面這樣寫代碼:-
public static SSLContext getSSLContextObject() {
if (sslContext == null) {
InputStream certificateInputStream = null;
CertificateFactory certificateFactory = null;
Certificate certificate = null;
String keyStoreType = null;
KeyStore keyStore = null;
String trustManagerAlgorithm = null;
TrustManagerFactory trustManagerFactory = null;
try {
certificateFactory = CertificateFactory.getInstance("X.509");
certificateInputStream = new BufferedInputStream(FliplearnApp
.getInstance().getAssets().open("certificateName.any.crt"));
try {
certificate = certificateFactory
.generateCertificate(certificateInputStream);
} finally {
certificateInputStream.close();
}
// Create a KeyStore containing our trusted CAs
keyStoreType = KeyStore.getDefaultType();
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("certificate", certificate);
// Create a TrustManager that trusts the CAs in our KeyStore
trustManagerAlgorithm = TrustManagerFactory
.getDefaultAlgorithm();
trustManagerFactory = TrustManagerFactory
.getInstance(trustManagerAlgorithm);
trustManagerFactory.init(keyStore);
// Create an SSLContext that uses our TrustManager
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagerFactory.getTrustManagers(),
null);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
return sslContext;
}
不需要,您不需要使用SSL上下文對象來編寫代碼,如下所示:-
public class Api {
private SSLContext sslContext;
private int lastResponseCode;
public int getLastResponseCode() {
return lastResponseCode;
}
public Api(AuthenticationParameters authParams) throws Exception {
File clientCertFile = authParams.getClientCertificate();
sslContext = getSSLContextObject();
CookieHandler.setDefault(new CookieManager());
}
public String doGet(String url) throws Exception {
String result = null;
HttpURLConnection urlConnection = null;
try {
URL requestedUrl = new URL(url);
urlConnection = (HttpURLConnection) requestedUrl.openConnection();
if(urlConnection instanceof HttpsURLConnection) {
((HttpsURLConnection)urlConnection).setSSLSocketFactory(sslContext.getSocketFactory());
}
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(1500);
urlConnection.setReadTimeout(1500);
lastResponseCode = urlConnection.getResponseCode();
result = IOUtil.readFully(urlConnection.getInputStream());
} catch(Exception ex) {
result = ex.toString();
} finally {
if(urlConnection != null) {
urlConnection.disconnect();
}
}
return result;
}
}
現在,您需要將上述代碼集成到截擊中。
您可以將設備類型甚至設備ID發送為網絡呼叫的標頭參數。 因此,在服務器端,您可以驗證標頭中發送的設備和ID是android還是其他,因此可以訪問。 這有幫助嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.