2014-10-06 23 views
0

我正在为nodeJS中的API开发API,以用于PassportJS的验证部分。 我使用这个很好的教程:http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-localPassportJS req.user从Android应用程序验证时未定义

在浏览器中,没关系我得到的用户,但是当我尝试使用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); 
     }); 
    }); 

})); 

而且我的Android代码:

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头请求应该与浏览器不同,所以它不能正常工作。

感谢您的帮助。

+0

你的意思护照JS(没有密码JS)硬编码的URL – Alex 2014-10-06 17:04:45

+0

是对不起我的编辑自己的帖子 – Marchah 2014-10-06 17:05:23

+0

当你说“在浏览器中,我可以找到用户,但是当我尝试使用android应用程序时,req.user未定义。” - 你什么意思?你要去哪个网址? – Alex 2014-10-06 17:06:06

回答

1

你expressjs服务器返回302 Moved Temporarily

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); 
    
  • 后手动跟随的URL重定向,在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")"

+0

我做了2个修改,现在我有用户在req在loginSuccess。但之后,当我想要访问一个路由,检查用户是否登录(这正是功能ligne 66:https://github.com/scotch-io/easy-node-authentication/blob/local/app/routes .js),API告诉我用户没有登录。是因为我必须把cookie放在get请求中吗?如果是的话,有一种简单的方法来转换Cookies中的字符串?感谢您的帮助 – Marchah 2014-10-09 18:22:51

+0

为会话数据创建一个单例类,保存来自'String cookie = conn.getHeaderField(“Set-Cookie”)的Cookie;'POST请求,在那里。或者只是[使用'SharedPreferences'](http://developer.android.com/guide/topics/data/data-storage.html#pref),保存一个bool'sessionValid'和一个字符串'sessionCookie',使用它与你的服务器的所有交互。 'conn.setRequestProperty(“Cookie”,sessionCookie);' – ashoke 2014-10-09 18:46:28

+0

所以我改变了我的GET请求由POST进行测试,因为POST请求可以在字符串中取得cookie但不取得GET请求。现在它正在工作。我认为它没有工作,因为饼干丢失。感谢您的帮助。 – Marchah 2014-10-09 19:18:26