在 android 中维护会话(应用程序在服务器端保持身份验证)



我正在 android 中构建一个登录应用程序,其中我点击一个 url(带有用户名和密码)直到该部分它工作正常,但之后每当我点击一个 url(一旦用户通过身份验证),它什么也不返回(即错误消息,例如请先登录)。但是,它在非常相似的iPhone应用程序和浏览器上工作正常。

我到了某个地方,这是phpSessionId的错误(即会话被销毁以供进一步请求),如果我们希望我们的Android应用程序在服务器端保持身份验证,我们需要在第一次连接后获取该id,然后将其发送到所有后续请求的标头中。

但问题是我无法从第一个连接的标头中获取 sessionId,并将其与标头一起发送进一步的请求。

请给我一些代码或链接以正确完成任务。谢谢。

最后,我解决了Android中的会话处理问题。Android 无法处理会话本身(简单的浏览器可以),因此我们必须显式处理它。我稍微更改了 http 连接的代码。建立连接时,在第一个活动中创建了 DefaultHttpClient 的实例。

public static DefaultHttpClient httpClient;

第一次连接时,我做了以下工作:

URL url=new URL(urlToHit);
LoginScreen.httpClient = new DefaultHttpClient(); //LoginScreen is the name of the current Activity
HttpPost httppost = new HttpPost(url.toString());
HttpResponse response = LoginScreen.httpClient.execute(httppost); 
xr.parse(new InputSource(url.openStream())); //SAX parsing

现在对于所有进一步的连接,我使用相同的httpClient例如,在下一个活动中:

URL url=new URL(urlToHit);
HttpPost httppost = new HttpPost(url.toString());
HttpResponse response = LoginScreen.httpClient.execute(httppost); 
// Log.v("response code",""+response.getStatusLine().getStatusCode());
// Get hold of the response entity
HttpEntity entity = response.getEntity();
InputStream instream = null;
if (entity != null) {
    instream = entity.getContent();
}
xr.parse(new InputSource(instream)); //SAX parsing

希望这也可以帮助您解决Android中的会话问题

最好的主意是将服务器执行的所有功能放在唯一的类上,该类将由想要连接的任务调用。我称这个类为WebServiceManager。此类具有与服务器完全相同的方法。

如你想要一个独特的会话做:

private static WebServiceManager wsm = null;
public static WebServiceManager getInstance() {
    if (wsm == null) {
        wsm = new WebServiceManager();
    }
    return wsm;
}
private final HttpClient httpClient;
private WebServiceManager() {
    httpClient=new DefaultHttpClient();
}

然后调用 webServiceManager 实例的方法以始终使用相同的会话。 :)

我的问题是我先登录并将返回的会话保存在用户首选项中。之后,POST 调用以设置记录说

"错误,无法对用户进行身份验证"

所以我添加了 post.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN); 整个事情看起来像这样。

HttpPost post=new HttpPost(URL );  
post.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN);    

..它解决了问题。

不久前我在coderwall上写了一篇关于它的文章它使用HttpRequestInterceptor和HttpResponseInterceptor类,非常适合这种情况。

下面是一个示例:

public class HTTPClients {
private static DefaultHttpClient _defaultClient;
private static String session_id;
private static HTTPClients _me;
private HTTPClients() {
}
public static DefaultHttpClient getDefaultHttpClient(){
    if ( _defaultClient == null ) {
        _defaultClient = new DefaultHttpClient();
        _me = new HTTPClients();
        _defaultClient.addResponseInterceptor(_me.new SessionKeeper());
        _defaultClient.addRequestInterceptor(_me.new SessionAdder());
    }
    return _defaultClient;
}
private class SessionAdder implements HttpRequestInterceptor {
    @Override
    public void process(HttpRequest request, HttpContext context)
            throws HttpException, IOException {
        if ( session_id != null ) {
            request.setHeader("Cookie", session_id);
        }
    }
}
private class SessionKeeper implements HttpResponseInterceptor {
    @Override
    public void process(HttpResponse response, HttpContext context)
            throws HttpException, IOException {
        Header[] headers = response.getHeaders("Set-Cookie");
        if ( headers != null && headers.length == 1 ){
            session_id = headers[0].getValue();
        }
    }
}

}

这是另一个使用 Volley 库的实现......来自 https://stackoverflow.com/a/36496607/3099185 的一个非常有用的提示

    CustomRequest jsonObjReq = new CustomRequest(Request.Method.GET,
            url, null,  new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
                Log.d(TAG, response.toString());
        }
    }, new Response.ErrorListener(){
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
            Toast.makeText(getApplicationContext(),
                    error.getMessage(), Toast.LENGTH_SHORT).show();
            // hide the progress dialog
        }
    });

自定义请求类

import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class CustomRequest extends JsonObjectRequest {
    private String session_id = "";
    public CustomRequest(int method, String url, JSONObject jsonRequest,
                                   Response.Listener listener, Response.ErrorListener errorListener) {
        super(method, url, jsonRequest, listener, errorListener);
    }
    public CustomRequest(int method, String url, JSONObject jsonRequest, String session_id,
                                   Response.Listener listener, Response.ErrorListener errorListener) {
        super(method, url, jsonRequest, listener, errorListener);
        this.session_id = session_id;
    }

    @Override
    public Map getHeaders() throws AuthFailureError {
        Map headers = new HashMap();
        Log.d(TAG, " -> session_id = " + session_id);
        if(!(session_id.equals(""))) {
            headers.put("Cookie", this.session_id);
        }
        return headers;
    }
}

使用单例模式实现凌空抽射的简单方法http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/

请记住在 onCreate() 中初始化 mRequestQueue,以避免意外的空指针异常

@Override
public void onCreate() {
    super.onCreate();
    // initialize the singleton
    sInstance = this;
        mRequestQueue = Volley.newRequestQueue(this);
}

希望这也有帮助... ! :)

相关内容

  • 没有找到相关文章

最新更新