2014-10-06 30 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