Android - 让用户在活动之间登录

时间:2015-02-27 10:52:26

标签: java android

在我的应用中,我发布了第一个允许您登录网络服务的活动。如果服务器允许用户连接,则应调用TabHost活动。在TabHost活动中,我有3种不同的活动:

  • HomeActivity:它只显示一个webview
  • HistoryActivity:它应显示我在其中插入通知历史记录的ListView
  • 设置活动:显示应用的一些设置

在HistoryActivity中,我要调用Web服务来下载通知历史记录列表。要调用此服务我是否可以让用户登录,我该怎么做?

我使用以下代码连接到历史服务:

public void postData(String url) {
    HttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(url);

    try {
        StringEntity  jsonSend = new StringEntity("{\"history\": true}");
        httpPost.setHeader("Content-type", "application/json; charset=UTF-8");
        httpPost.setEntity(jsonSend);
        HttpResponse response = httpClient.execute(httpPost);

        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
        StringBuilder builder = new StringBuilder();

        for (String line = null; (line = reader.readLine()) != null;) {
            builder.append(line).append("\n");
        }
        String json = builder.toString();
        Log.d("HISTORY", json);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我用它登录,效果很好。要连接到登录服务,我使用以下代码:

public void postData(final String username, final String password) {
    HttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(url);

    try {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("username", username));
        nameValuePairs.add(new BasicNameValuePair("password", password));
        nameValuePairs.add(new BasicNameValuePair("pollingId", "XXXXXXXXX"));

        httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");

        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        HttpResponse response = httpClient.execute(httpPost);

        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
        StringBuilder builder = new StringBuilder();

        for (String line = null; (line = reader.readLine()) != null;) {
            builder.append(line).append("\n");
        }

        String json = builder.toString();

        JSONObject jsonObject = new JSONObject(json);
        Boolean success = jsonObject.getBoolean("success");

        if (success == true) {
            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "ACCESSO EFFETTUATO!", Toast.LENGTH_LONG).show();
                    Intent i = new Intent(MainActivity.this, TabBarActivity.class);
                    startActivity(i);
                }
            });
        }

    } catch (ClientProtocolException e) {
       Log.d("CLIENT EXCEPTION", "ERRORE: " + e);
    }catch (IOException e) {
       Log.d("I/O EXCEPTION", "ERRORE: " + e);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

如果我用它来获取通知历史记录,JSON告诉我用户没有登录。我该怎么办呢?谢谢

更新 我试图按照你的建议,但我得到了同样的结果。修改后的代码如下:

MainActivity.java

public void postData(final String username, final String password) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost("https://extranet.gruppotesta.it/srv/at-brain/login.jsp");

        try {
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            nameValuePairs.add(new BasicNameValuePair("username", username));
            nameValuePairs.add(new BasicNameValuePair("password", password));
            nameValuePairs.add(new BasicNameValuePair("pollingId", "XXXXXXX"));

            httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");

            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            HttpResponse response = httpClient.execute(httpPost);

            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
            StringBuilder builder = new StringBuilder();

            for (String line = null; (line = reader.readLine()) != null;) {
                builder.append(line).append("\n");
            }

            String json = builder.toString();

            JSONObject jsonObject = new JSONObject(json);
            Boolean success = jsonObject.getBoolean("success");

            if (success == true) {
                Header[] cookie = response.getHeaders("cookie");
                SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString("cookie", cookie.toString());
                editor.commit();
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "ACCESSO EFFETTUATO!", Toast.LENGTH_LONG).show();
                        Intent i = new Intent(MainActivity.this, TabBarActivity.class);
                        startActivity(i);
                    }
                });
            }

        } catch (ClientProtocolException e) {
           Log.d("CLIENT EXCEPTION", "ERRORE: " + e);
        }catch (IOException e) {
           Log.d("I/O EXCEPTION", "ERRORE: " + e);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

HistoryActivity.java

   public void postData(String url) {
        HttpClient httpClient = new DefaultHttpClient();

        SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
        String stringCookie = sharedPreferences.getString("cookie", null);
        BasicCookieStore cookieStore = new BasicCookieStore();
        Cookie cookie = new BasicClientCookie("login", stringCookie);
        cookieStore.addCookie(cookie);

        HttpContext localContext = new BasicHttpContext();
        localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        HttpPost httpPost = new HttpPost(url);

        try {
            StringEntity jsonRequest = new StringEntity("{\"history\": true}");
            httpPost.setEntity(jsonRequest);
            httpPost.setHeader("Content-type", "application/json; charset=UTF-8");
            httpPost.setHeader("Cookie", cookie.toString());

            HttpResponse response = httpClient.execute(httpPost, localContext);

            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
            StringBuilder builder = new StringBuilder();

            for (String line = null; (line = reader.readLine()) != null;) {
                builder.append(line).append("\n");
            }
            String json = builder.toString();
            Log.d("HISTORY", json);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

当我尝试运行应用程序时,服务器会回答我错误&#34;用户未记录&#34;。我的代码有什么问题?

3 个答案:

答案 0 :(得分:1)

首次登录时,Web服务必须为您提供某种访问令牌 - 可能是有效的用户ID 。您需要在SharedPreference中存储和检索此用户ID 。必须将此用户ID 作为参数传递给所有后续Web服务,以指示用户确实已登录。

如何获取和设置SharedPreference的官方教程是here

答案 1 :(得分:0)

您可以尝试使用CookieStore存储带有登录凭据的cookie。请看一下这个链接:Http cookie store in Android

答案 2 :(得分:0)

您的服务在成功登录后是否会回赠会话cookie?如果是这样,您应该存储服务在登录后发出的cookie(在来自服务器的响应中的Set-Cookie标头中),并为将来的任何HTTP请求设置此cookie。

httpPost.setHeader("Cookie", COOKIE_FROM_SERVER_AFTER_LOGIN);

您也可以使用CookieStore来帮助您存储来自HTTP请求的Cookie - 这样可以简化Cookie和会话管理。

<强>更新

服务器标题不会包含Cookie标题但是Set-Cookie标题(因为服务器正在指示您的useragent / browser /客户端设置Cookie并且它是否为此Cookie这将包含在您的Cookie标题中),因此请更改此行:

response.getHeaders("cookie");

response.getHeaders("set-cookie"); 

<强>更新

您的修订现在正在提取正确的Set-Cookie标题,但您错误地存储了该值(当您需要的是值时,您将整个标题存储为Cookie。)

if (success == true) {

    Header[] cookies = response.getHeaders("set-cookie");
    //at this point cookies looks like this:
    //Set-Cookie: JSESSIONID=84DB43CE8CABC52EBDF777BC0EA96D0F; Path=/; Secure
    //if you just do cookies.toString() like you were doing before it will also include
    //the cookie header which will create an incorrect cookie value.
    //you just need the value of the Set-Cookie header and store that as your cookie
    if (cookies.length > 0){

        //it is very possible for a server to return more than one Set-Cookie header so the proper
        //way would be to iterate through all of the values and string them together
        //in the correct synatax of
        //so you might want to store all of the values as a list in sharedPreferences
        //and let your cookie store put them all in the request for you

        String finalCookie = "";

        for (Header header: cookies){

            //access the value from the Header object and nothing else
            //JSESSIONID=90D84EF5D5BD1C4008F332F9EDA8F9AA; Path=/; Secure;
            if (header.getValue().contains(";")){
                finalCookie += String.format("%s; ", header.getValue().split(";")[0]);
            } else {
                finalCookie += String.format("%s; ", header.getValue());
            }
        }
        //finalCookie = JSESSIONID=1B70CAB822430E14991E14ACAE153F5D; 

        SharedPreferences sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("cookie", finalCookie);
        editor.commit();
    }

现在,在您的StoredPreferences中,您将拥有格式正确的Cookie(在您的情况下,您只从服务器返回一个,但可能在服务器响应中包含多个Set-Cookie标头。因此,此实现解析每个cookie并以正确的格式构建cookie字符串。

由于我们现在正在自己构建cookie字符串,因此您可以删除CookieStore并只需提取&#34; cookie&#34;使用SharedPreferences中的值并使用setHeader调用中返回的字符串:

SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
String stringCookie = sharedPreferences.getString("cookie", "");
...
httpPost.setHeader("Cookie", cookie);

请注意,虽然此实施方案对您有用,但如果Cookie在整个会话期间发生变化,则不会考虑此问题。由于您是Web应用程序的作者,因此您应该知道cookie是否发生变化 - 也许当您登录时,您唯一一次在浏览器中设置cookie并且此解决方案对您有用。但更强大的解决方案是单独保存所有cookie(而不是使用editor.putString,您可以使用editor.putStringSet保存所有cookie标头)然后当您想要为响应构建cookie时你可以.add()每个cookie到cookie商店,然后像以前一样使用cookie商店。这样,每个cookie的名称都会单独存储,这样如果您再次为已经加载到客户端的cookie获取另一个Set-Cookie标头,它将使用更新的cookie值正确覆盖该值。