问题
I have created a form in angular, On click of submit button I am hitting a post request with Content-Type
header with value application/x-www-form-urlencoded
.
onSubmit(user:User) {
let headers = new Headers();
// to send data as form data as passport library want it as a form data
headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post('/login', user, { headers: headers }).subscribe((data) => {
console.log("Data : ", data);
});
}
and the model user is of type
// Class to bind user data
class User {
constructor(private name: string, private password: string) {
}
}
Here is the server side code
let userList: User[] = [new User(1, "Sunil"), new User(2, "Sukhi")];
let app = express();
// passport library
let passport = require('passport');
let LocalStrategy = require('passport-local').Strategy;
// middlewares
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ resave: false, saveUninitialized: true, secret: "secretKey123!!" }));
// passport middleware invoked on every request to ensure session contains passport.user object
app.use(passport.initialize());
// load seriliazed session user object to req.user
app.use(passport.session());
// Only during the authentication to specify what user information should be stored in the session.
passport.serializeUser(function (user, done) {
console.log("Serializer : ", user)
done(null, user.userId);
});
// Invoked on every request by passport.session
passport.deserializeUser(function (userId, done) {
let user = userList.filter(user => userId === user.userId);
console.log("D-serializer : ", user);
// only pass if user exist in the session
if (user.length) {
done(null, user[0]);
}
});
// passport strategy : Only invoked on the route which uses the passport.authenticate middleware.
passport.use(new LocalStrategy({
usernameField: 'name',
passwordField: 'password'
},
function (username, password, done) {
console.log("Strategy : Authenticating if user is valid :", username)
let user = userList.filter(user => username === user.userName);
console.log("Valid user : ",user)
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
return done(null, user[0]);
}
));
app.post('/login', passport.authenticate('local', {
successRedirect: '/done',
failureRedirect: '/login'
}));
app.get('/done', function (req, res) {
console.log("Done")
res.send(req.session)
})
app.get('/login', function (req, res) {
console.log("login")
res.send("login")
})
but every time it is returning login
回答1:
In my case, the issue was with the request body. I was sending the user object directly so this was not working. To solve this I have created the body object using URLSearchParams
.
let body = new URLSearchParams();
body.append('name', this.user.name);
body.append('password', this.user.password);
Here is the onSubmit
method
onSubmit() {
let body = new URLSearchParams();
body.append('name', this.user.name);
body.append('password', this.user.password);
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
let options = new RequestOptions({headers});
this.http.post("/services/login", body.toString(), options).subscribe((response)=>{
let arrUrl = response.url.split("/");
let url = "/" + arrUrl[arrUrl.length-1];
this.router.navigate([url]);
});
}
Second, from the login form, I was not passing the value for password
field. So the local strategy's callback(with username and password) was not getting called.
If you don't pass any of the fields then the callback method will not be called and will redirect to the failureRedirect
URL.
来源:https://stackoverflow.com/questions/47034310/passport-js-not-working-with-manual-form-data-post-request-angular