我正在使用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
我使用express4.0但我也尝试过express3.8。 我完全迷失了,我根本不明白为什么它可以与浏览器配合使用而不是应用程序。
编辑:我认为问题来自我在Android中调用API的方式,http标头请求应该与浏览器不同,因此它不能正常工作。
感谢您的帮助。
答案 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")"