如何通过google api和sha1从android安全进行服务器请求调用?

时间:2018-02-07 06:05:00

标签: php android

我正在创建一个始终调用服务器来加载数据(JSON数据)的应用程序。 像谷歌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);

2 个答案:

答案 0 :(得分:1)

因此需要首先学习用于Android的SSL,并且需要在服务器端创建SSL证书。

<强>概念

  

在典型的SSL使用方案中,服务器配置了一个   包含公钥和匹配私钥的证书。   作为SSL客户端和服务器之间握手的一部分,服务器   通过签署证书证明它有私钥   public-key加密。

For more info read link

  

以下示例将使这些概念更加具体。   在命令行下面的代码片段中,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;
    }
}

现在您需要将上面的代码集成到您的排球中。

答案 1 :(得分:0)

您可以将设备类型甚至设备ID作为网络呼叫的标头参数发送。因此,在服务器端,您可以验证标头中发送的设备和标识是否为android或其他,因此可以访问或不可访问。这有帮助吗?