使用Android登录时未设置Passport.js会话

时间:2016-07-29 12:06:31

标签: android node.js session sails.js passport.js

在我的AuthController.js中,我检查登录是否成功并在会话中设置哈希码:

 req.logIn(user, function (err) {
                if (err) res.send(err);
                var redirectTo = req.session.redirectTo ? req.session.redirectTo : '/user/show/'+user.id;
                delete req.session.redirectTo;

                bcrypt.genSalt(10, function (err, salt) {
                    bcrypt.hash(user.email, salt, function (err, hash) {
                        if (err) {
                            console.log(err);
                        } else {


                            req.session.passport.user_type = user.type;
                            req.session.passport.user_avatar = user.avatar;
                            req.session.passport.email = user.email;
                            req.session.passport.token = hash;

                             // here session is set! also when login with Android 
                                console.log("User passport Sessions: ",req.session.passport)

                                res.json(user);
                                res.end();

                        }
                    });
                })

            })

当我使用浏览器登录时设置会话 - 我用另一个简单的控制器检查它们:

'who': function (req, res) {
        res.json(req.session);
    },

当我使用我的Android应用程序(Volley Request)登录时,一切都按预期工作,但是当我成功登录后向这个'who'控制器发出新请求时,整个'passport'属性为空。

当我使用Android App登录时,为什么没有设置护照会话?

问题是:排球请求是否与浏览器请求不同?当服务器无法保存会话请求时,如何在服务器上知道(在第二个请求中)该用户已经登录?

我转储了req.headers,这就是Chrome的样子:

{ host: 'localhost:1337',
  connection: 'keep-alive',
  'cache-control': 'max-age=0',
  'upgrade-insecure-requests': '1',
  'user-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  'accept-encoding': 'gzip, deflate, sdch',
  'accept-language': 'de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4',
  cookie: '__utma=111872281.1508283337.1455636609.1455636609.1455636609.1; __utmz=111872281.1455636609.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _ga=GA1.1.1508283337.1455636609; sails.sid=s%3AHNW3D3ktwA79IFHH4gX9Ko6o73MZOjRK.I7sTYkCKSkkwset6OC2ap58fcROPtV6PqUnkaInGW44',
  'if-none-match': 'W/"1f3e-WoreHgYUy3uvXGNH++ttsQ"' }

这就是Android对Volley的请求:

{ 'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86 Build/MASTER)',
  host: '10.0.2.2:1337',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip' }
{ 'if-none-match': 'W/"1f3e-WoreHgYUy3uvXGNH++ttsQ"',
  'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86 Build/MASTER)',
  host: '10.0.2.2:1337',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip' }

缺少会话部分 - 同时我知道您必须自己实施会话管理。是否有一个简单的教程,可以通过会话在Volley上发出多个HTTP请求?

1 个答案:

答案 0 :(得分:2)

好的10天后,我知道如何修复"此

当您向服务器发出请求时,您会收到很多回复。标题对我们来说很重要。

在此处阅读有关HTTP标头的更多信息: http://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039

HTTP请求是无状态的,这意味着,它不会保存有关客户端的信息和状态。

Volley没有处理标题。我们要做的是:

当我们从我们的应用程序发出第一个请求时,我们必须保存响应头信息。

{"Access-Control-Allow-Credentials":"","Access-Control-Allow-Headers":"","Access-Control-Allow-Methods":"","Access-Control-Allow-Origin":"","Access-Control-Expose-Headers":"","Connection":"keep-alive","Content-Length":"235","Content-Type":"application\/json; charset=utf-8","Date":"Tue, 09 Aug 2016 22:39:40 GMT","ETag":"W\/\"eb-bxZXjFIir0ihzYNPgoUbTg\"","set-cookie":"sails.sid=s%3AsjQL1FsAJY5VWGHdgChpa0hgZPs06AH9z.H1RLNh%2FMqLjxdGtKtnWFv8cFO8WjeAUhPFQp2Yl73Lo; Path=\/; HttpOnly","Vary":"X-HTTP-Method-Override","X-Android-Received-Millis":"1470713694296","X-Android-Response-Source":"NETWORK 200","X-Android-Selected-Protocol":"http\/1.1","X-Android-Sent-Millis":"1470713694119","X-Powered-By":"Sails <sailsjs.org>"}

标题中的重要信息是&#34; set-cookie&#34;部分。我们必须从第一次调用中保存这些信息,并在每次下一次请求时重复使用它,以便服务器知道我们是谁。

如何?

我使用了来自djodjo的这个自定义请求。重要的方法是 parseNetworkResponse https://stackoverflow.com/a/36435582/3037960

我们像这样使用那个类:

mHeaders = new HashMap<String, String>(); 
    session = new SessionManager(myView.getContext());

 registerRequest = new MetaRequest(1, MY_ENDPOINT, obj, new Response.Listener<JSONObject>() {

                    @Override
                        public void onResponse(JSONObject response) {

                            JSONObject headers = new JSONObject();
                            try {
                                headers.put("headers", response.get("headers"));
   // get the "set-cookie" value
                                String sailsSession = String.valueOf(headers.getJSONObject("headers").get("set-cookie"));
                                Log.d("Response Headers", sailsSession);

                                // Session Manager
                                session.storeSailsSession(sailsSession);

                                String cookie = session.getSailsSession();

                                if( cookie != null) {
                                   //just to test if the cookie is now saved?
                                    Log.d("Cookies", cookie);
                                }

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }

                        }
                    }, new Response.ErrorListener() {

                        @Override
                        public void onErrorResponse(VolleyError error) {
                                Log.d("ERROR", String.valueOf(error));
                            // TODO Auto-generated method stub

                        }
                    }){

                        public Map<String, String> getHeaders() {
                            return mHeaders;
                        }
                    };

                    RequestQueue queue = Volley.newRequestQueue(getActivity());
                    queue.add(registerRequest);

你看到那里有会话管理器...... session.storeSailsS​​ession(sailsS​​ession); 这是一个自定义类,用于在共享首选项中保存我们的cookie,这样我们就可以得到这些信息我们需要时在应用程序中整体使用它们。

public class SessionManager {
    // Shared Preferences
    SharedPreferences pref;

    // Editor for Shared preferences
    Editor editor;

    // Context
    Context _context;


    // User hash/cookie
    public static final String KEY_SESSION = "session";

    // Constructor
    public SessionManager(Context context){
        this._context = context;
        pref = _context.getSharedPreferences(PREF_NAME, 0);
        editor = pref.edit();
    }


    public void storeSailsSession(String session){
        editor.putString(KEY_SESSION,session);
        editor.commit();

       }
 public String getSailsSession(){
        return pref.getString(KEY_SESSION,null);
    }

    }

您现在可以看到如何从标题中获取Cookie,以及如何将其存储以供日后使用;现在为nex请求如何设置标头?

在您发送请求之前(您不必使用上面的自定义MetaRequest),您必须从共享首选项中获取会话,然后在哈希映射中设置mHeaders:

String sailsCookie =  session.getSailsSession();
mHeaders.put("cookie", sailsCookie.toString());

并且不要忘记将 mHeaders 返回到您的请求中,如下所示:

JsonArrayRequest arrayreq = new JsonArrayRequest(JsonURL,Listener,ErrorListener){
                public Map<String, String> getHeaders() {
                    return mHeaders;
                }
}

通常你只使用 new WhatEverRequest(....); 但现在你必须附上 {... return mHeaders;}

我希望你理解它,否则只是发表评论,我会解释它。对我而言,它确实有效,所以我相信它也适合你。下次我建议您使用https://jwt.io