在我的应用中,我发布了第一个允许您登录网络服务的活动。如果服务器允许用户连接,则应调用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();
}
}
}
当我尝试运行应用程序时,服务器会回答我错误&#34;用户未记录&#34;。我的代码有什么问题?
答案 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值正确覆盖该值。