首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Thinkster.io教程部分:使用Postman中的注册请求创建帐户

Thinkster.io教程部分:使用Postman中的注册请求创建帐户
EN

Stack Overflow用户
提问于 2019-03-25 21:22:46
回答 1查看 134关注 0票数 0

Thinkster.io链接https://thinkster.io/tutorials/node-json-api/setting-up-users-and-authentication

我向应用程序api发送的任何邮递员请求都会收到一个404。

这是我从postman那里得到的错误“在评估测试脚本时出现错误: JSONError:意外的令牌'<‘at 1:1^”,但它实际上是一个404,我在我的控制台中得到了这个"POST /users 404 0.396 ms - 145“

Postman screenshot

我想这可能是我的路线,但我又看了一遍教程,现在我想我在Postman中做错了什么。我通过Thinksters Postman遍历,以及我在他们的服务器上的所有测试工作,但不知道我遗漏了什么。

app.js

代码语言:javascript
复制
var fs = require('fs'),
    http = require('http'),
    path = require('path'),
    methods = require('methods'),
    express = require('express'),
    bodyParser = require('body-parser'),
    session = require('express-session'),
    cors = require('cors'),
    passport = require('passport'),
    errorhandler = require('errorhandler'),
    mongoose = require('mongoose');

var isProduction = process.env.NODE_ENV === 'production';

// Create global app object
var app = express();

app.use(cors());

// Normal express config defaults
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use(require('method-override')());
app.use(express.static(__dirname + '/public'));

app.use(session({ secret: 'conduit', cookie: { maxAge: 60000 }, resave: false, saveUninitialized: false  }));

if (!isProduction) {
  app.use(errorhandler());
}

if(isProduction){
  mongoose.connect(process.env.MONGODB_URI);
} else {
  mongoose.connect('mongodb://localhost/conduit');
  mongoose.set('debug', true);
}

require('./models/User');//Be sure to include models before routes so that our routes will be able to use our models. this allows us to use the user model with auth
require('./config/passport');//username and password auth middleware for login endpoint /login
app.use(require('./routes'));

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (!isProduction) {
  app.use(function(err, req, res, next) {
    console.log(err.stack);

    res.status(err.status || 500);

    res.json({'errors': {
      message: err.message,
      error: err
    }});
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.json({'errors': {
    message: err.message,
    error: {}
  }});
});

// finally, let's start our server...
var server = app.listen( process.env.PORT || 3000, function(){
  console.log('Listening on port ' + server.address().port);
});

routes/user.js

代码语言:javascript
复制
var mongoose = require('mongoose');
var router = require('express').Router();
var passport = require('passport');
var User = mongoose.model('User');
var auth = require('../auth');

//We rely on Mongoose validations to ensure that users are created with a username or password. When user.save() is called, a promise is returned for us to handle. If the promise is resolved, that means the user was saved successfully, and we return the user's auth JSON. If the promise gets rejected, we use .catch() to pass the error to our error handler.
router.post('/users', function(req, res, next){
  var user = new User();

  user.username = req.body.user.username;
  user.email = req.body.user.email;
  user.setPassword(req.body.user.password);

  user.save().then(function(){
    return res.json({user: user.toAuthJSON()});
  }).catch(next);
});


//First, we're checking to make sure an email and password were provided by the front-end and respond with a 422 status code if they're not. Then, we pass the incoming request to passport.authenticate and specify that we want to use the local strategy we made previously (in config/passport.js). Since we're using JWTs for authentication and not using sessions, we also specify {session: false} to prevent Passport from serializing the user into the session. Finally, we define a callback for the passport strategy (this gets used as the done function in our LocalStrategy in config/passport.js) that will respond to the client based off if the authentication was successful or not.
router.post('/users/login', function(req, res, next){

  if(!req.body.user.email){
    return res.status(422).json({errors: {email: "can't be blank"}});
  }

  if(!req.body.user.password){
    return res.status(422).json({errors: {password: "can't be blank"}});
  }
  //While we can implement this functionality without the use of Passport in our route, an advantage to using Passport is that it gives us the ability to add other authentication strategies such as OAuth in the future.
  passport.authenticate('local', {session: false}, function(err, user, info){
    if(err){ return next(err); }

    if(user){
      user.token = user.generateJWT();
      return res.json({user: user.toAuthJSON()});
    } else {
      return res.status(422).json(info);
    }
  })(req, res, next);
});

router.get('/user', auth.required, function(req, res, next){
  User.findById(req.payload.id).then(function(user){
    if(!user){ return res.sendStatus(401); }

    return res.json({user: user.toAuthJSON()});
  }).catch(next);
});

router.put('/user', auth.required, function(req, res, next){
  User.findById(req.payload.id).then(function(user){
    if(!user){ return res.sendStatus(401); }

    // only update fields that were actually passed...
    if(typeof req.body.user.username !== 'undefined'){
      user.username = req.body.user.username;
    }
    if(typeof req.body.user.email !== 'undefined'){
      user.email = req.body.user.email;
    }
    if(typeof req.body.user.bio !== 'undefined'){
      user.bio = req.body.user.bio;
    }
    if(typeof req.body.user.image !== 'undefined'){
      user.image = req.body.user.image;
    }
    if(typeof req.body.user.password !== 'undefined'){
      user.setPassword(req.body.user.password);
    }

    return user.save().then(function(){
      return res.json({user: user.toAuthJSON()});
    });
  }).catch(next);
});
module.exports = router;

routes/index.js

代码语言:javascript
复制
var router = require('express').Router();

router.use('/api', require('./api'));

module.exports = router;

routes/api/index.js

代码语言:javascript
复制
var router = require('express').Router();

router.use('/', require('./users'));

//When a middleware is defined with four arguments, it will be treated as an error handler (the first argument is always the error object). This error handler sits after all of our API routes and is used for catching ValidationErrors thrown by mongoose. The error handler then parses the error into something our front-end can understand, and then responds with a 422 status code.
router.use(function(err, req, res, next){
  if(err.name === 'ValidationError'){
    return res.status(422).json({
      errors: Object.keys(err.errors).reduce(function(errors, key){
        errors[key] = err.errors[key].message;

        return errors;
      }, {})
    });
  }

  return next(err);
});

module.exports = router;

models/User.js

代码语言:javascript
复制
var mongoose = require('mongoose'); //handles models/schema for mongodb i/o
var uniqueValidator = require('mongoose-unique-validator');//builting in unique combo validation
var crypto = require('crypto'); //library that generates and validates hashes
var jwt = require('jsonwebtoken');
var secret = require('../config').secret;//We need a secret to sign and validate JWT's. This secret should be a random string that is remembered for your application; it's essentially the password to your JWT's. In config/index.js there's a secret value which is set to "secret" in development and reads from an environment variable in production.

var UserSchema = new mongoose.Schema({
  username: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/^[a-zA-Z0-9]+$/, 'is invalid'], index: true},
  email: {type: String, lowercase: true, unique: true, required: [true, "can't be blank"], match: [/\S+@\S+\.\S+/, 'is invalid'], index: true},
  image: String,
  hash: String,
  salt: String
}, {timestamps: true});


//plugging in a validator defind above, unique:true must be used for validation
UserSchema.plugin(uniqueValidator, {message: 'is already taken.'});

//To see if a password is valid for a particular user, we need to run the pbkdf2 with the same number of iterations and key length as our setPassword function with the salt of the user; then we need to check to see if the resulting hash matches the one that's stored in the database.
UserSchema.methods.setPassword = function(password){
  this.salt = crypto.randomBytes(16).toString('hex');
  this.hash = crypto.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512').toString('hex');
};

//Next, we'll need a method on our model for generating a JWT (JSON Web Token). JWT's are the tokens that will be passed to the front-end that will be used for authentication. The JWT contains a payload (assertions) that is signed by the back-end, so the payload can be read by both the front-end and back-end, but can only be validated by the back-end.
UserSchema.methods.validPassword = function(password) {
 var hash = crypto.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512').toString('hex');
 return this.hash === hash;
};

//Lastly, we'll need a method on the user model to get the JSON representation of the user that will be passed to the front-end during authentication. This JSON format should only be returned to that specific user since it contains sensitive information like the JWT.
UserSchema.methods.generateJWT = function() {
  var today = new Date();
  var exp = new Date(today);
  exp.setDate(today.getDate() + 60);

  return jwt.sign({
    id: this._id,
    username: this.username,
    exp: parseInt(exp.getTime() / 1000),
  }, secret);
};

UserSchema.methods.toAuthJSON = function(){
  return {
    username: this.username,
    email: this.email,
    token: this.generateJWT(),
    bio: this.bio,
    image: this.image
  };
};
mongoose.model('User', UserSchema);
EN

回答 1

Stack Overflow用户

发布于 2019-03-25 23:58:37

看起来/user路由需要身份验证。我的猜测是,您的Postman脚本不包含包含JWT的所需身份验证头

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55338802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档