node.js - 护照验证功能不起作用
问题描述
我正在尝试按照本教程在我的 React 应用程序中实现 Twitter 身份验证。
我创建了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
写对了吗?似乎根本没有调用该函数。还有其他使用方法吗?
谢谢!
解决方案
如果身份验证成功,则 passport.authenticate 继续下一个回调,否则返回一个授权代码。
1.你的回调函数中是否插入了断点或日志?
2.他们被召唤了吗?
3.端点是否被调用?
您可以查看本教程进行护照身份验证,因为它非常详细,可以指导您了解其工作原理: http ://scottksmith.com/blog/2014/05/02/building-restful-apis-with-节点/
编辑:
我只能与您分享一段我用于使用护照进行基本身份验证的代码。它可以工作,但它没有使用 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 方法中,您可以 res.send 并在那里结束该过程,而不是转到下一个回调,而不是调用您的下一个服务器功能。
希望能帮助到你
推荐阅读
- react-native - 尝试在 WSL 上安装 React-Native 需要资源
- c++ - 带有 ODBC 驱动程序的 PostgreSQL“光标未定位在一行上”
- asp.net-core - ASP.NET Core WebAPI XML 方法参数反序列化
- python - 为什么我不断收到 AttributeError:'NoneType' 对象没有属性 'lower'?
- python - 如何使用python循环XML文件中的标签
- python - 如何重定向到 Django 页面上的特定位置?
- google-cloud-platform - 将 PR 构建用作 Google Cloud 触发构建的子域
- arrays - 如何在 C 中获取包含 const 数组的 const 结构的正确大小
- java - 在 Java 中使用多态性替换 If/Else
- c# - 在 C# 中声明变量