[英]Android - Keep user logged between activities
在我的应用程序中,我具有允许您登录到Web服务的第一个活动。 如果服务器允许用户连接,则应调用TabHost活动。 在TabHost活动中,我有3个不同的活动:
在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();
}
}
}
当我尝试运行该应用程序时,服务器用错误“用户未登录”回答我。 我的代码有什么问题?
首次登录时,Web服务必须为您提供某种访问令牌-也许是有效的用户ID 。 您需要在SharedPreference
存储和检索此用户ID 。 该用户标识必须作为参数传递给所有后续的Web服务,以指示该用户确实已登录。
有关如何获取和设置SharedPreference
的官方教程在这里 。
您可以尝试使用CookieStore来存储具有登录凭据的cookie。 看一下此链接: Android中的Http cookie存储 。
成功登录后,您的服务是否还提供会话cookie? 如果是这样,您应该存储登录后服务发出的cookie(在服务器响应中的Set-Cookie标头中),并为以后的任何HTTP请求设置此cookie。
httpPost.setHeader("Cookie", COOKIE_FROM_SERVER_AFTER_LOGIN);
您也可以使用CookieStore来帮助您存储来自HTTP请求的cookie-这将使cookie和会话管理更加容易。
UPDATE
服务器标头将不包含Cookie
标头,但包含Set-Cookie
标头(因为服务器正在指示您的useragent /浏览器/客户端设置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
,但是服务器响应中可能包含多个Set-Cookie
标头。因此,此实现会解析每个cookie并构建正确格式的Cookie字符串。
由于我们现在自己正确地构建了cookie字符串,因此您可以删除CookieStore并从SharedPreferences中拉出“ cookie”值,并使用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值正确覆盖该值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.