我正在尝试按照this教程在我的React应用程序中实现Twitter身份验证。
我已经创建了用于处理请求令牌和 authentication 部分的脚本(user.controller.js
)。一切正常,但似乎并不是每个函数都被调用。
因此,在前端部分,我在控制台中收到以下消息:POST http://localhost:5000/api/auth/twitter?oauth_verifier=MY-OAUTH-VERIFIER&oauth_token=MY-OAUTH-TOKEN 404 (Not Found)
此外,我正在使用react-twitter-auth
,如下所示:
import React, { Component } from 'react';
import 'bulma/css/bulma.css'
import { Link } from 'react-router-dom';
import TwitterLogin from 'react-twitter-auth';
class Header extends Component {
constructor() {
super();
this.state = { isAuthenticated: false, user: null, token: '' };
}
onSuccess = (response) => {
const token = response.headers.get('x-auth-token');
response.json().then(user => {
if (token) {
this.setState({isAuthenticated: true, user: user, token: token});
}
});
};
onFailed = (error) => {
alert(error);
};
logout = () => {
this.setState({isAuthenticated: false, token: '', user: null})
};
render() {
let content = !!this.state.isAuthenticated ?
(
<div>
<p>Authenticated</p>
<div>
{this.state.user.email}
</div>
<div>
<button onClick={this.logout} className="button" >
Log out
</button>
</div>
</div>
) :
(
<TwitterLogin
loginUrl="http://localhost:5000/api/auth/twitter"
onFailure={this.onFailed} onSuccess={this.onSuccess}
requestTokenUrl="http://localhost:5000/api/auth/twitter/reverse"
className="button" />
);
return (
<header className="navbar has-shadow is-spaced">
<div className="container">
<div className="navbar-brand">
<h1 className="title is-4">
<Link to="#" className="navbar-item">
<strong>Voting App</strong>
</Link>
</h1>
</div>
<div className="navbar-end">
<div className="buttons">
{content}
</div>
</div>
</div>
</header>
);
}
}
导出默认标题;
这是user.controller.js
代码:
var mongoose = require('mongoose'),
User = mongoose.model('User'),
passport = require('passport'),
express = require('express'),
jwt = require('jsonwebtoken'),
expressJwt = require('express-jwt'),
router = express.Router(),
cors = require('cors'),
request = require('request'),
twitterConfig = require('../twitter.config.js');
var passportConfig = require('../passport');
// setup configuration for twitter login
passportConfig();
var createToken = function(auth) {
return jwt.sign({
id: auth.id
}, 'my-secret',
{
expiresIn: 60 * 120
});
};
var generateToken = function (req, res, next) {
req.token = createToken(req.auth);
return next();
};
var sendToken = function (req, res) {
res.setHeader('x-auth-token', req.token);
return res.status(200).send(JSON.stringify(req.user));
};
module.exports.requestTokenUrl = (req, res) => {
request.post({
url: 'https://api.twitter.com/oauth/request_token',
oauth: {
oauth_callback: "http%3A%2F%2Flocalhost%3A3000%2F",
consumer_key: twitterConfig.consumerKey,
consumer_secret: twitterConfig.consumerSecret
}
}, function (err, r, body) {
if (err) {
return res.send(500, { message: e.message });
}
var jsonStr = '{ "' + body.replace(/&/g, '", "').replace(/=/g, '": "') + '"}';
res.send(JSON.parse(jsonStr));
});
};
module.exports.authenticateUser = (req, res, next) => {
request.post({
url: 'https://api.twitter.com/oauth/access_token?oauth_verifier',
oauth: {
consumer_key: twitterConfig.consumerKey,
consumer_secret: twitterConfig.consumerSecret,
token: req.query.oauth_token
},
form: { oauth_verifier: req.query.oauth_verifier }
}, function (err, r, body) {
if (err) {
return res.send(500, { message: e.message });
}
const bodyString = '{ "' + body.replace(/&/g, '", "').replace(/=/g, '": "') + '"}';
const parsedBody = JSON.parse(bodyString);
req.body['oauth_token'] = parsedBody.oauth_token;
req.body['oauth_token_secret'] = parsedBody.oauth_token_secret;
req.body['user_id'] = parsedBody.user_id;
next();
});
}, passport.authenticate('twitter', {session: false}), function(req, res, next) {
if (!req.user) {
return res.send(401, 'User Not Authenticated');
}
// prepare token for API
req.auth = {
id: req.user.id
};
return next();
}, (generateToken, sendToken);
//token handling middleware
var authenticate = expressJwt({
secret: 'my-secret',
requestProperty: 'auth',
getToken: function(req) {
if (req.headers['x-auth-token']) {
return req.headers['x-auth-token'];
}
return null;
}
});
这是路由器脚本:
var express = require('express');
var router = express.Router();
var ctrlUsers = require('../controller/user.controller.js');
router.route('/health-check').get(function(req, res) {
res.status(200);
res.send('Hello World');
});
// Routes
router
.route('/auth/twitter/reverse')
.post(ctrlUsers.requestTokenUrl);
router
.route('/auth/twitter')
.post(ctrlUsers.authenticateUser);
module.exports = router;
所以我的问题是:passport.authenticate
书写正确吗?似乎根本没有调用该函数。还有其他使用方式吗?
谢谢!
答案 0 :(得分:0)
passport.authenticate继续进行下一个回调,否则返回一个授权代码。
1。您是否在任何回调函数中插入了任何断点或日志?
2。他们被叫吗?
3。是否正在调用端点?
您可以查看此护照认证教程,因为它非常详细,可以指导您了解其工作原理: http://scottksmith.com/blog/2014/05/02/building-restful-apis-with-node/
编辑:
我只能与您分享我用于使用护照进行基本身份验证的一部分代码。它可以工作,但是没有使用Twitter,因此您可以尝试一下,然后进行相应的修改。
在我的身份验证控制器中,我有以下代码:
const passport = require('passport');
const BasicStrategy = require('passport-http').BasicStrategy;
const User = require('../models/user');
passport.use(new BasicStrategy(
function(email, password, callback) {
User.findOne({ email: email }, function (err, user) {
if (err) { return callback(err); }
// No user found with that email
if (!user) { return callback(null, false); }
// Make sure the password is correct
user.verifyPassword(password, function(err, isMatch) {
if (err) { return callback(err); }
// Password did not match
if (!isMatch) { return callback(null, false); }
// Success
// console.log(user);
return callback(null, user);
});
});
}
));
exports.isAuthenticated = passport.authenticate(['basic', 'bearer'], { session : false });
在我的用户模型中,我具有此功能来验证密码(您需要bcrypt才能使用它):
const bcrypt = require('bcrypt-nodejs');
UserSchema.methods.verifyPassword = function (password, cb) {
bcrypt.compare(password, this.password, function (err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
然后在路线中我像这样使用它:
const express = require('express');
let anotherRouter = express.Router();
let anotherController= require('../controllers/another');
let authController = require('../controllers/auth');
anotherRouter.route('/another/route')
.post(authController.isAuthenticated,anotherController.postSomething);
当然,在isAuthenticated方法中,您可以重新发送并结束该过程,而不必调用下一个服务器功能,而无需转到下一个Callback。
希望有帮助