怎么调试nodejs restful API 以及API的Authorization

最近Nodejs,python越来越火了,同时也越来越多的人在用node写服务,可是怎么去调试服务呢?以及当你一个服务发布出去,怎么保证其安全性呢?

 

环境:linux unbuntu

语言:nodejs

工具:npm,mongodb,HttpIE

 

昨天写API的时候遇到了一个苦恼,就是我怎么去调试一个Api,当然有人会说客户端调用一下,然后debug模式就可以跟踪了,可是我昨天没有客户端,怎么办呢?后来找到了一个非常好的工具HttpIE,怎么安装可以参考 https://httpie.org/doc#linux,大家可能根据自己的开发环境去安装

example:

# Debian, Ubuntu, etc.

apt-get install httpie

# Fedora, CentOS, RHEL, …

yum install httpie

# Arch Linux

pacman -S httpie

不过万事都有不顺的时候,我在安装的时候遇到了一个问题

william@ubuntu:~$ sudo apt-get install httpie
[sudo] password for william: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
You might want to run 'apt-get -f install' to correct these:
The following packages have unmet dependencies:
 cpp-5 : Depends: gcc-5-base (= 5.4.0-6ubuntu1~16.04.2) but 5.4.0-6ubuntu1~16.04.4 is to be installed
 gcc-5 : Depends: cpp-5 (= 5.4.0-6ubuntu1~16.04.4) but 5.4.0-6ubuntu1~16.04.2 is to be installed
 google-chrome-stable : Depends: libappindicator1 but it is not going to be installed
 httpie : Depends: python-pygments but it is not going to be installed
          Depends: python-requests but it is not going to be installed
 libstdc++-5-dev : Depends: libstdc++6 (>= 5.4.0-6ubuntu1~16.04.4) but 5.4.0-6ubuntu1~16.04.2 is to be installed
 libstdc++6 : Depends: gcc-5-base (= 5.4.0-6ubuntu1~16.04.2) but 5.4.0-6ubuntu1~16.04.4 is to be installed
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).
william@ubuntu:~$ sudo apt-get -f install
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Correcting dependencies... Done
The following additional packages will be installed:
  cpp-5 libappindicator1 libindicator7 libstdc++6
Suggested packages:
  gcc-5-locales
The following NEW packages will be installed:
  libappindicator1 libindicator7
The following packages will be upgraded:
  cpp-5 libstdc++6
2 upgraded, 2 newly installed, 0 to remove and 441 not upgraded.
17 not fully installed or removed.
Need to get 0 B/8,088 kB of archives.
After this operation, 161 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
(Reading database ... 214296 files and directories currently installed.)
Preparing to unpack .../cpp-5_5.4.0-6ubuntu1~16.04.4_amd64.deb ...
Unpacking cpp-5 (5.4.0-6ubuntu1~16.04.4) over (5.4.0-6ubuntu1~16.04.2) ...
dpkg-deb (subprocess): decompressing archive member: lzma error: compressed data is corrupt
dpkg-deb: error: subprocess <decompress> returned error exit status 2
dpkg: error processing archive /var/cache/apt/archives/cpp-5_5.4.0-6ubuntu1~16.04.4_amd64.deb (--unpack):
 cannot copy extracted data for './usr/lib/gcc/x86_64-linux-gnu/5/cc1' to '/usr/lib/gcc/x86_64-linux-gnu/5/cc1.dpkg-new': unexpected end of file or stream
Errors were encountered while processing:
 /var/cache/apt/archives/cpp-5_5.4.0-6ubuntu1~16.04.4_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

 报错了,原因是需要清除掉缓存

william@ubuntu:~$ sudo apt-get clean

然后重复上面的操作(蓝色字体)的命令就可以完成了

怎么用HttpIE去调试API呢,比如我需要调试添加一条article记录怎么办呢? http://localhost:1337/api/articles,

$ http POST http://localhost:1337/api/articles title=TestArticle author='John Doe' description='lorem ipsum dolar sit amet' images:='[{"kind":"thumbnail", "url":"http://habrahabr.ru/images/write-topic.png"}, {"kind":"detail", "url":"http://habrahabr.ru/images/write-topic.png"}]'

看截图:

然后进入到了virtual studio code里面的断点:

 

怎么保证其安全性呢? 我用的是oauth2orize, https://www.npmjs.com/package/oauth2orize 

在调用的时候加入:

router.post('/', passport.authenticate('bearer', { session: false }), function(req, res) {

然后调用的时候,需要加入token:

william@ubuntu:~$ http POST http://localhost:1337/api/articles title=NewArticle author='John Doe' description='Lorem ipsum dolar sit amet' images:='[{"kind":"thumbnail", "url":"http://habrahabr.ru/images/write-topic.png"}, {"kind":"detail", "url":"http://habrahabr.ru/images/write-topic.png"}]' Authorization:'Bearer put your token here'

 passport 与oauth2orize 联合使用,其中有2个重要的概念AccessToken 和 RefreshToken, 为什么有了AccessToken还需要RefreshToken呢?因为token都会过期,需要运用RefreshToken去刷新AccessToken

 

var oauth2orize = require('oauth2orize');
var passport = require('passport');
var crypto = require('crypto');

var libs = process.cwd() + '/libs/';

var config = require(libs + 'config');
var log = require(libs + 'log')(module);

var db = require(libs + 'db/mongoose');
var User = require(libs + 'model/user');
var AccessToken = require(libs + 'model/accessToken');
var RefreshToken = require(libs + 'model/refreshToken');

// create OAuth 2.0 server
var aserver = oauth2orize.createServer();

// Generic error handler
var errFn = function (cb, err) {
    if (err) { 
        return cb(err); 
    }
};

// Destroys any old tokens and generates a new access and refresh token
var generateTokens = function (data, done) {

    // curries in `done` callback so we don't need to pass it
    var errorHandler = errFn.bind(undefined, done), 
        refreshToken,
        refreshTokenValue,
        token,
        tokenValue;

    RefreshToken.remove(data, errorHandler);
    AccessToken.remove(data, errorHandler);

    tokenValue = crypto.randomBytes(32).toString('hex');
    refreshTokenValue = crypto.randomBytes(32).toString('hex');

    data.token = tokenValue;
    token = new AccessToken(data);

    data.token = refreshTokenValue;
    refreshToken = new RefreshToken(data);

    refreshToken.save(errorHandler);

    token.save(function (err) {
        if (err) {
            
            log.error(err);
            return done(err); 
        }
        done(null, tokenValue, refreshTokenValue, { 
            'expires_in': config.get('security:tokenLife') 
        });
    });
};

// Exchange username & password for access token.
aserver.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) {
    
    User.findOne({ username: username }, function(err, user) {
        
        if (err) { 
            return done(err); 
        }
        
        if (!user || !user.checkPassword(password)) {
            return done(null, false);
        }

        var model = { 
            userId: user.userId, 
            clientId: client.clientId 
        };

        generateTokens(model, done);
    });

}));

// Exchange refreshToken for access token.
aserver.exchange(oauth2orize.exchange.refreshToken(function(client, refreshToken, scope, done) {

    RefreshToken.findOne({ token: refreshToken, clientId: client.clientId }, function(err, token) {
        if (err) { 
            return done(err); 
        }

        if (!token) { 
            return done(null, false); 
        }

        User.findById(token.userId, function(err, user) {
            if (err) { return done(err); }
            if (!user) { return done(null, false); }

            var model = { 
                userId: user.userId, 
                clientId: client.clientId 
            };

            generateTokens(model, done);
        });
    });
}));

// token endpoint
//
// `token` middleware handles client requests to exchange authorization grants
// for access tokens.  Based on the grant type being exchanged, the above
// exchange middleware will be invoked to handle the request.  Clients must
// authenticate when making requests to this endpoint.

exports.token = [
    passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
    aserver.token(),
    aserver.errorHandler()
];
View Code

 

 创建AccessToken和RefreshToken

http POST http://localhost:1337/api/oauth/token grant_type=password client_id=android client_secret=SomeRandomCharsAndNumbers username=myapi password=abc1234
http POST http://localhost:1337/api/oauth/token grant_type=refresh_token client_id=android client_secret=SomeRandomCharsAndNumbers refresh_token=[TOKEN]

 

posted on 2017-07-20 16:10  张江style  阅读(1940)  评论(0编辑  收藏  举报

导航