使用 JWT 对 json-server 进行授权

Posted

技术标签:

【中文标题】使用 JWT 对 json-server 进行授权【英文标题】:Authorizarion on json-server with a JWT 【发布时间】:2020-06-12 22:55:33 【问题描述】:

我正在尝试制作一个使用 typicode json-server 的节点应用程序,我想向应用程序添加授权,其中 GET 请求对所有公众开放,但 PUT、POST 和 DELETE 请求需要 JWT 令牌,然后才他们可以继续使用 api。

我尝试制作一个小应用程序,但由于我是前端开发人员,我无法弄清楚授权的下一部分以及如何在节点上使用中间件。

这是我编写的应用程序。

    const jsonServer = require('json-server')
    const app = jsonServer.create()
    const router = jsonServer.router('db.json')
    const middlewares = jsonServer.defaults()
    const morgan = require('morgan');
    const jwt = require('jsonwebtoken');
    const config = require('./config');
    const bodyParser = require('body-parser');

    app.set('Secret', config.secret);
    app.use(morgan('dev'));
    app.use(bodyParser.urlencoded( extended: true ));
    app.use(bodyParser.json());

    app.use(middlewares)
    app.use((req, res, next) => 
        if (req.method === 'GET') 
            console.log(req);
            next();
         else 
            if (req.path === '/login') 
                getToken(req, res);
            
            if (isAuthorized(req, res)) 
                console.log("I am here");
                next();
             else 
                console.log("I am in error");
                res.sendStatus(401)
            
        
    )
    app.use(router)
    app.listen(3000, () => 
        console.log('JSON Server is running on 3000')
    )

    function isAuthorized(req, res) 

        console.log("sadasdasdasd");

        var token = req.headers['access-token'];
        console.log(token);
        // decode token
        if (token) 
            console.log("Inside token");
            jwt.verify(token, app.get('Secret'), (err, decoded) => 
                console.log("Inside JWT fn");
                if (err) 
                    console.log("Inside JWT fn err");
                    return res.json( message: 'invalid token' );
                 else 
                    console.log("Inside JWT fn success");
                    req.decoded = decoded;
                    return true;
                
            );

         else 
            // if there is no token  
            res.send(
                message: 'No token provided.'
            );
        
    

    function getToken(req, res) 
        if (req.body.username === "test") 
            if (req.body.password === 123) 
                const payload = 
                    check: true
                ;
                var token = jwt.sign(payload, app.get('Secret'), 
                    expiresIn: 1440 // expires in 24 hours
                );
                res.json(
                    message: 'Authentication Successful ',
                    token: token
                );
             else 
                res.json(
                    error: 'Invalid Password',
                );
            
         else 
            res.json(
                error: 'Please provide valid credentials',
            );
        
     

【问题讨论】:

【参考方案1】:

你做对了。但是,您的 isAuthorized 中间件有一些问题。在中间件中你有一个异步动作(jwt.verify),那么你不能像json-server的官方文档那样把这个函数作为一个“辅助函数”(函数返回布尔值)。

isAuthorized成为一个中间件,你就像一个中间件:

function isAuthorized(req, res, next)  // Pass 3 parmas to a express middleware 

  console.log("sadasdasdasd");

  var token = req.headers['access-token'];
  console.log(token);
  // decode token
  if (token) 
    console.log("Inside token");
    jwt.verify(token, app.get('Secret'), (err, decoded) => 
      console.log("Inside JWT fn");
      if (err) 
        console.log("Inside JWT fn err");
        return res
          .status(401) // I think will be better if you throw http status is 401 to client
          .json( message: 'invalid token' );
       else 
        console.log("Inside JWT fn success");
        req.decoded = decoded;
        return next(); // Only call "next" if everything is good, continue next jobs - handle secured requests
      
    );

   else 
    // if there is no token  
    return res
    .status(401)
    .send(
      message: 'No token provided.'
    );
  

使用中间件

    app.use((req, res, next) => 
        if (req.method === 'GET') 
            console.log(req);
            next();
         else 
            if (req.path === '/login') 
                getToken(req, res);
            
            isAuthorized(req, res, next); // Here
        
    )

【讨论】:

以上是关于使用 JWT 对 json-server 进行授权的主要内容,如果未能解决你的问题,请参考以下文章

基于角色的 jwt 授权

如何使用 Identity Server 4 (JWT) 进行基于角色的 Web API 授权

使用 Axios 和 Vue.js 进行 JWT 授权(标题)

使用 Django GraphQL JWT 和 Graphene Relay 进行身份验证和授权

将 JWT 与基于角色的授权一起使用

护照-jwt 总是返回 401 未授权