为啥我收到的 jwt 格式错误?

Posted

技术标签:

【中文标题】为啥我收到的 jwt 格式错误?【英文标题】:Why am I receiving jwt malformed?为什么我收到的 jwt 格式错误? 【发布时间】:2019-11-23 04:00:42 【问题描述】:

我正在尝试在我的个人资料组件中登录后检索我的 jwt 令牌,并将该令牌存储在本地存储中。我知道 localstorage 不是最佳选择,但这将是一个本地移动应用程序,因此我所知道的 localstorage 是我的最佳选择。但是当我登录时,我收到了一个令牌,这是我最近收到的一个令牌

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaGVjayI6dHJ1ZSwiaWF0IjoxNTYzMDUzMzk4LCJleHAiOjE1NjMwNTQ4Mzh9.tw8ks-jFZID5rmwhoNTkWV8598niE3zMFIDk4Gz-sVg

当我的 Profile 组件尝试检索 /current 时,它使用 jwt 格式错误

服务器.js

var express = require('express');
var cors = require('cors');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 5000;
var morgan = require('morgan');
const auth = require('./middleware/auth');
const User = require('./models/User');

app.use(cors());
app.use(
  bodyParser.urlencoded(
    extended: false
  )
);

app.use(bodyParser.json());

/*========= Here we want to let the server know that we should expect and allow a header with the content-type of 'Authorization' ============*/
app.use((req, res, next) => 
  res.setHeader('Access-Control-Allow-Headers', 'Content-type,Authorization');
  next();
);

// use morgan to log requests to the console
app.use(morgan('dev'));

var Users = require('./routes/Users');

app.use('/users', Users);

// Create a Server
const PORT = process.env.PORT || 5000; // Environment variable or port 5000

app.listen(PORT, () => console.log(`Server started on port $PORT`));

module.exports = app;

用户.js

const express = require('express');
const users = express.Router();
const cors = require('cors');
const jwt = require('jsonwebtoken');
var exjwt = require('express-jwt');

var jwtauth = require('../middleware/authjwt.js');
const bcrypt = require('bcrypt');
const bodyParser = require('body-parser');
const User = require('../models/User');
const config = require('config');
const auth = require('../middleware/auth');
const secret = 'dasdsad';

users.use(
  bodyParser.urlencoded(
    extended: true
  )
);

users.use(bodyParser.json());

users.use(cors());

users.post('/register', (req, res) => 
  const today = new Date();
  const userData = 
    first_name: req.body.first_name,
    last_name: req.body.last_name,
    email: req.body.email,
    password: req.body.password,
    created: today
  ;

  User.findOne(
    where: 
      email: req.body.email
    
  )
    //TODO bcrypt
    //Need validation to appear on console and in view
    .then(user => 
      if (!user) 
        bcrypt.hash(req.body.password, 10, (err, hash) => 
          userData.password = hash;
          User.create(userData)
            .then(user => 
              res.json( status: user.email + 'Registered!' );
            )
            .catch(err => 
              res.send('error: ' + err);
            );
        );
       else 
        res.json( error: 'User already exists' );
      
    )
    .catch(err => 
      res.send('error: ' + err);
    );
);

users.post('/authenticate', (req, res) => 
  User.findOne(
    where: 
      email: req.body.email
    
  ).then(user => 
    if (user) 
      if (bcrypt.compareSync(req.body.password, user.password)) 
        const payload = 
          check: true
        ;

        const token = jwt.sign(payload, config.get('myprivatekey'), 
          expiresIn: 1440 // expires in 24 hours
        );

        res.json(
          message: 'authentication done ',
          token: token
        );
        console.log('Successful Login');
        console.log(user.first_name);
       else 
        res.json( message: 'please check your password !' );
        console.log('incorrect password');
      
     else 
      res.json( message: 'user not found !' );
      console.log('user cannot be found');
    
  );
);

//users.get('/something', [express.bodyParser(), jwtauth], function(req, res) 
// do something
//);

// app.all('/api/*', [express.bodyParser(), jwtauth]);

users.get(
  '/current',
  exjwt( secret: config.get('myprivatekey') ),
  async (req, res) => 
    const user = await User.findById(req.user._id).select('-password');
    console.log(user);
    res.send(user);
  
);

登录

import React,  Component  from 'react';

class Login extends Component 
  constructor() 
    super();
    this.state = 
      email: '',
      password: '',
      errors: 
    ;

    this.onChange = this.onChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  

  onChange(e) 
    this.setState( [e.target.name]: e.target.value );
  
  onSubmit(e) 
    e.preventDefault();

    const user = 
      email: this.state.email,
      password: this.state.password
    ;

    var token = window.localStorage.getItem('token');

    fetch('http://localhost:5000/users/authenticate', 
      method: 'POST', // or 'PUT'
      body: JSON.stringify(user), // data can be `string` or object!
      headers: 
        'Content-Type': 'application/json'
      
    );
  

  render() 
    return (
      <div className='container'>
        <div className='row'>
          <div className='col-md-6 mt-5 mx-auto'>
            <form noValidate onSubmit=this.onSubmit>
              <h1 className='h3 mb-3 font-weight-normal'>Please sign in</h1>
              <div className='form-group'>
                <label htmlFor='email'>Email address</label>
                <input
                  type='email'
                  className='form-control'
                  name='email'
                  placeholder='Enter email'
                  value=this.state.email
                  onChange=this.onChange
                />
              </div>
              <div className='form-group'>
                <label htmlFor='password'>Password</label>
                <input
                  type='password'
                  className='form-control'
                  name='password'
                  placeholder='Password'
                  value=this.state.password
                  onChange=this.onChange
                />
              </div>
              <button
                type='submit'
                className='btn btn-lg btn-primary btn-block'
              >
                Sign in
              </button>
            </form>
          </div>
        </div>
      </div>
    );
  


export default Login;

这就是我目前在“我的个人资料”组件中获取令牌的方式

 componentDidMount() 
    var token = localStorage.getItem('token');
    fetch('http://localhost:5000/users/current', 
      //cahng taht
      method: 'GET',
      mode: 'cors',
      headers:  Authorization: 'Bearer ' + token 
    );
  

【问题讨论】:

你能登录config.get('myprivatekey')吗? 【参考方案1】:

我猜问题出在 expiresIn 上。 'expiresIn' 以秒或描述时间跨度的字符串表示。您设置了 1440,这意味着 1440/60 = 24minutes => 24 分钟后过期,而不是 24 小时后...请尝试如下设置:

const token = jwt.sign(payload, config.get('myprivatekey'), 
          expiresIn: '24h' // expires in 24 hours
        );

【讨论】:

以上是关于为啥我收到的 jwt 格式错误?的主要内容,如果未能解决你的问题,请参考以下文章

Azure AD - 为啥我无法验证 Azure AD 为我的 Web API 颁发的 JWT 令牌?收到“IDX10516:签名验证失败”错误

_generate_jwt_token中的格式字符串无效

为啥在 Heroku 服务器上为 Laravel JWT 身份验证收到此错误

为啥我会收到这种错误验证错误?

JWT 未解码“JWT 格式错误”-Node Angular

JSONWebTokenError:JWT 在 index.js 处格式错误