首页 > 解决方案 > 护照验证功能不起作用

问题描述


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

标签: node.jsreactjsauthenticationpassport.js

解决方案


如果身份验证成功,则 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 并在那里结束该过程,而不是转到下一个回调,而不是调用您的下一个服务器功能。

希望能帮助到你


推荐阅读