簡體   English   中英

如何使用sha1使來自Android安全的服務器請求調用(如google api)安全?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM