护照验证功能不起作用

时间:2018-10-23 14:00:53

标签: node.js reactjs authentication passport.js


我正在尝试按照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书写正确吗?似乎根本没有调用该函数。还有其他使用方式吗?
谢谢!

1 个答案:

答案 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。

希望有帮助