从Android应用程序验证时,PassportJS req.user未定义

时间:2014-10-06 17:00:00

标签: android node.js express passport.js passport-local

我正在使用PassportJS在nodeJS中开发一个API,用于身份验证部分I' m。 我正在使用这个好的教程:http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-local

在浏览器中,我可以得到用户但是当我尝试使用Android应用时,req.user是未定义的。

app.post('/login', passport.authenticate('local-login', {
    successRedirect: '/loginSuccess',
    failureRedirect: '/loginFailure',
    failureFlash : true // allow flash messages
}));

app.get('/loginFailure', function(req, res, next) {
    res.setHeader('Content-Type', 'application/json');
    res.json({user: req.user, message: req.flash('loginMessage')[0]});
});

app.get('/loginSuccess', function(req, res, next) {
    console.log(req.user);
    res.setHeader('Content-Type', 'application/json');
    res.json({user: req.user, message: "test"});
});

//

passport.use('local-login', new LocalStrategy({
    usernameField : 'login',
    passwordField : 'password',
    passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, login, password, done) {
    // asynchronous
    process.nextTick(function() {
        User.findOne({$or:[{'local.email': login.toLowerCase()}, {'local.login': login}]}, function(err, user) {
            // if there are any errors, return the error
            if (err)
                return done(err);

            // if no user is found, return the message
            if (!user)
                return done(null, false, req.flash('loginMessage', 'No user found.'));

            if (!user.validPassword(password))
                return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));

            // all is well, return user
            else
                return done(null, user);
        });
    });

}));

我的安卓代码:

public class LoginActivity extends Activity {

      private Button loginButton = null;
      private Button cancelButton = null;


      private boolean isOnline() {
            ConnectivityManager cm =
                (ConnectivityManager) getSystemService(AppInfo.getAppContext().CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            if (netInfo != null && netInfo.isConnectedOrConnecting()) {
                return true;
            }
            return false;
        }

      private OnClickListener clickListenerLoginButton = new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isOnline()) {
                    Toast.makeText(LoginActivity.this, getResources().getString(R.string.ERROR_NO_NETWORK), Toast.LENGTH_LONG).show();
                    return ;
                }
                new LoginOperation().execute(getResources().getString(R.string.urlLogin));
            }
        };

        private OnClickListener clickListenerCancelButton = new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent result = new Intent();
                setResult(RESULT_CANCELED, result);
                finish();
            }
        };

      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        loginButton = (Button)findViewById(R.id.loginButton);
        cancelButton = (Button)findViewById(R.id.cancelButton);

        loginButton.setOnClickListener(clickListenerLoginButton);
        cancelButton.setOnClickListener(clickListenerCancelButton);
      }

      private Object user;

      private class LoginOperation  extends AsyncTask<String, Void, Void> {

        String Response = "";
        String Error = null;
        String data ="";
        private ProgressDialog Dialog = new ProgressDialog(LoginActivity.this);
        EditText login_emailEditText = (EditText) findViewById(R.id.login_emailEditText);
        EditText passwordEditText = (EditText) findViewById(R.id.passwordEditText);

        protected void onPreExecute() {

            Dialog.setMessage("Please wait..");
            Dialog.show();

            try{
                data += "&"+URLEncoder.encode("login", "UTF-8")+ "=" +URLEncoder.encode(login_emailEditText.getText().toString(), "UTF-8");
                data += "&"+URLEncoder.encode("password", "UTF-8")+ "=" +URLEncoder.encode(passwordEditText.getText().toString(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        }

        @Override
        protected Void doInBackground(String... urls) {
            BufferedReader reader=null;
                try
                {
                   URL url = new URL(urls[0]);
                  // Send POST data request
                  URLConnection conn = url.openConnection();
                  conn.setDoOutput(true);
                  OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
                  wr.write( data );
                  wr.flush();

                  // Get the server response
                  reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                  StringBuilder sb = new StringBuilder();
                  String line = null;

                    // Read Server Response
                    while((line = reader.readLine()) != null) {
                        sb.append(line + " ");
                    }

                    // Append Server Response To Content String
                   Response = sb.toString();
                }
                catch(Exception ex) {
                    Error = ex.getMessage();
                }
                finally {
                    try {
                        reader.close();
                    }
                    catch(Exception ex) {}
                }
            return null;
        }

        protected void onPostExecute(Void unused) {
            Dialog.dismiss();

            if (Error != null) {
                Toast.makeText(LoginActivity.this, "ErrorAndroid: " + Error, Toast.LENGTH_LONG).show();
            } else {
                try {
                    JSONObject jsonObject = new JSONObject(Response);
                    Toast.makeText(LoginActivity.this, jsonObject.toString(), Toast.LENGTH_LONG).show();
                    user = jsonObject.get("user");
                } catch (JSONException e) {
                    Toast.makeText(LoginActivity.this, "ErrorAndroidJSON: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }

             }
        }

      }
}

尝试使用浏览器: USER1 /密码1

http://exemple.com:4040/login

我使用express4.0但我也尝试过express3.8。 我完全迷失了,我根本不明白为什么它可以与浏览器配合使用而不是应用程序。

编辑:我认为问题来自我在Android中调用API的方式,http标头请求应该与浏览器不同,因此它不能正常工作。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

你表示服务器正在返回&#34; 302 Moved Temporarily&#34;

    HTTP/1.1 302 Moved Temporarily
    X-Powered-By: Express
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Headers: Content-Type
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
    Location: /loginSuccess
    Vary: Accept
    Content-Type: text/html; charset=UTF-8
    Content-Length: 82
    Date: Wed, 08 Oct 2014 23:29:31 GMT
    Connection: keep-alive

"Location"设置为/loginSuccess;

默认情况下

Android URLConnection 会自动跟随重定向,并且会向您提取/loginSuccess

返回的数据

问题是,您的expressjs服务器要求您发回它设置的cookie;

所以解决方案是

  • 禁用自动重定向;在初始url.openConnection()

    之后添加以下行
    ((HttpURLConnection)conn).setInstanceFollowRedirects(false);
    
  • 手动关注网址重定向,并在GET请求中设置cookie值。在wr.flush();

    之后添加以下代码段
    String cookie = conn.getHeaderField("Set-Cookie");
    conn = new URL("http://example.com:4040/loginSuccess").openConnection();
    conn.setRequestProperty("Cookie", cookie);
    conn.connect();
    
  • 考虑使用"baseUrl + conn.getHeaderField("Location")"

  • 替换上面的硬编码网址