代码之家  ›  专栏  ›  技术社区  ›  Rohan Ashik Manoj Srivastava

如何从android安全地调用服务器请求,比如使用sha1的google api?

  •  0
  • Rohan Ashik Manoj Srivastava  · 技术社区  · 7 年前

    我正在制作一个总是调用服务器来加载数据(JSON数据)的应用程序。 像google api一样,我如何确保POST请求是否来自我的android应用程序。 如何确保这一点?

    下面给出了我一直向php服务器发送POST requst的代码

    下面的代码发送了手机和密码等数据以进行登录 但如果有人从我的android应用程序中复制并在他们的应用程序中使用。然后服务器将被黑客攻击。如何防止 只接受来自android应用程序的POST请求,不接受来自任何其他来源的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 回复  |  直到 7 年前
        1
  •  1
  •   duggu Neeraj Nama    7 年前

    所以需要学习android的第一个SSL,并且需要在服务器端创建SSL证书。

    概念

    在典型的SSL使用场景中,服务器配置为 包含公钥和匹配私钥的证书。 作为SSL客户端和服务器之间握手的一部分,服务器 通过在证书上签名来证明其具有私钥 public-key 密码学。

    For more info read link

    下面的示例将使这些概念更加具体。 在下面的命令行代码段中,openssl工具的\u客户端 命令查看Wikipedia的服务器证书信息。它 指定端口443,因为这是HTTPS的默认端口。命令 将openssl s\U客户端的输出发送到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;
        }
    }
    

    现在,您需要将上述代码集成到您的截击中。

        2
  •  0
  •   Yashaswi N P    7 年前

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