一歩一歩、ノードを設定するガイドです.パスポートJWTとのJS API
43774 ワード
認証と認証はアプリケーションの大部分です.保護やチェックなしにAPIルートがあるたびに、アプリケーションは簡単にハッカーのターゲットになることができます.だから私たちは安全なトークンを必要とするのです — the JSON Web Token (JWT) .
UNT JWTの基礎
私はあまり深くJWTに行くつもりはないが、ここですべての基本です.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
JSONのWebトークンをエンコードし、ユーザーの情報をデコードします.彼らは認可と情報交換に使用されます.
三つの部分から成る — ヘッダー、ペイロード、および署名 — ドットで区切られた.
) このように:xxxxx.yyyyy.zzzzz
JSONウェブトークンについてもっと読むhere .
始める前に
お使いのコンピュータが既に持っていると仮定しますnpm そして、これをチェックしないならば、Postmanでテストしてください.
ここではcode 場合は、プロセスとのトラブルを持ってトリヴィンのslack あなたが質問をする必要があるならば.
サーバの設定
独自のサーバーを使用する場合は、この手順をスキップします.
あなたがプロジェクトを持っていないならば、我々は使用しますTrivin プロジェクトテンプレートを設定するにはこの記事では、簡単なノードサーバーを作成するために使用します.
$ npm i trivin -g
$ trivin server simple-node-server -g -i
これはa simple but well-structured node-server , gitを初期化し、プロジェクトの依存関係をすべてインストールします.
インストール
$ npm i passport passport-jwt winston cors express-validator jsonwebtoken
セットアップファイルのサポート
$ mkdir store/
$ touch store/passport.js store/config.js store/utils.js controller/constant.js
定数。js
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
お使いのコンピュータが既に持っていると仮定しますnpm そして、これをチェックしないならば、Postmanでテストしてください.
ここではcode 場合は、プロセスとのトラブルを持ってトリヴィンのslack あなたが質問をする必要があるならば.
サーバの設定
独自のサーバーを使用する場合は、この手順をスキップします.
あなたがプロジェクトを持っていないならば、我々は使用しますTrivin プロジェクトテンプレートを設定するにはこの記事では、簡単なノードサーバーを作成するために使用します.
$ npm i trivin -g
$ trivin server simple-node-server -g -i
これはa simple but well-structured node-server , gitを初期化し、プロジェクトの依存関係をすべてインストールします.
インストール
$ npm i passport passport-jwt winston cors express-validator jsonwebtoken
セットアップファイルのサポート
$ mkdir store/
$ touch store/passport.js store/config.js store/utils.js controller/constant.js
定数。js
$ npm i trivin -g
$ trivin server simple-node-server -g -i
$ npm i passport passport-jwt winston cors express-validator jsonwebtoken
$ mkdir store/
$ touch store/passport.js store/config.js store/utils.js controller/constant.js
TextEditor
自動的に私のために完了し、文字列のtyposを減らす.constant.js
ファイルexport const EMAIL_IS_EMPTY = 'EMAIL_IS_EMPTY';
export const PASSWORD_IS_EMPTY = 'PASSWORD_IS_EMPTY';
export const PASSWORD_LENGTH_MUST_BE_MORE_THAN_8 =
'PASSWORD_LENGTH_MUST_BE_MORE_THAN_8';
export const WRONG_PASSWORD = 'WRONG_PASSWORD';
export const SOME_THING_WENT_WRONG = 'SOME_THING_WENT_WRONG';
export const USER_EXISTS_ALREADY = 'USER_EXISTS_ALREADY';
export const USER_DOES_NOT_EXIST = 'USER_DOES_NOT_EXIST';
export const TOKEN_IS_EMPTY = 'TOKEN_IS_EMPTY';
export const EMAIL_IS_IN_WRONG_FORMAT = 'EMAIL_IS_IN_WRONG_FORMAT';
Utilsjs
import sha256 from 'sha256';
import { check } from 'express-validator';
import {
PASSWORD_IS_EMPTY,
PASSWORD_LENGTH_MUST_BE_MORE_THAN_8,
EMAIL_IS_EMPTY,
EMAIL_IS_IN_WRONG_FORMAT,
} from './constant';
export const generateHashedPassword = password => sha256(password);
export function generateServerErrorCode(res, code, fullError, msg, location = 'server') {
const errors = {};
errors[location] = {
fullError,
msg,
};
return res.status(code).json({
code,
fullError,
errors,
});
}
// ================================
// Validation:
// Handle all validation check for the server
// ================================
export const registerValidation = [
check('email')
.exists()
.withMessage(EMAIL_IS_EMPTY)
.isEmail()
.withMessage(EMAIL_IS_IN_WRONG_FORMAT),
check('password')
.exists()
.withMessage(PASSWORD_IS_EMPTY)
.isLength({ min: 8 })
.withMessage(PASSWORD_LENGTH_MUST_BE_MORE_THAN_8),
];
export const loginValidation = [
check('email')
.exists()
.withMessage(EMAIL_IS_EMPTY)
.isEmail()
.withMessage(EMAIL_IS_IN_WRONG_FORMAT),
check('password')
.exists()
.withMessage(PASSWORD_IS_EMPTY)
.isLength({ min: 8 })
.withMessage(PASSWORD_LENGTH_MUST_BE_MORE_THAN_8),
];
パスポート。jsセットアップ
store/passport.js
:import { Strategy, ExtractJwt } from 'passport-jwt';
import { config, underscoreId } from './config';
import { User } from '../database/models';
export const applyPassportStrategy = passport => {
const options = {};
options.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
options.secretOrKey = config.passport.secret;
passport.use(
new Strategy(options, (payload, done) => {
User.findOne({ email: payload.email }, (err, user) => {
if (err) return done(err, false);
if (user) {
return done(null, {
email: user.email,
_id: user[underscoreId]
});
}
return done(null, false);
});
})
);
};
store/config.js
私はすべてのアプリケーションの私の構成を維持する場所です:export const config = {
passport: {
secret: '<Add_Your_Own_Secret_Key>',
expiresIn: 10000,
},
env: {
port: 8080,
mongoDBUri: 'mongodb://localhost/test',
mongoHostName: process.env.ENV === 'prod' ? 'mongodbAtlas' : 'localhost',
},
};
export const underscoreId = '_id';
変更するapp.js
パスポートで使用するには、次の手順に従います.import express from 'express';
import logger from 'winston';
import bodyParser from 'body-parser';
import cors from 'cors';
import passport from 'passport';
import mongoose from 'mongoose';
import { config } from './store/config';
import { applyPassportStrategy } from './store/passport';
import { userController } from './controller';
const app = express();
// Set up CORS
app.use(cors());
// Apply strategy to passport
applyPassportStrategy(passport);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// API Route
app.use('/', userController);
/**
* Get port from environment and store in Express.
*/
const { port, mongoDBUri, mongoHostName } = config.env;
app.listen(port, () => {
logger.info(`Started successfully server at port ${port}`);
mongoose
.connect(mongoDBUri, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
logger.info(`Conneted to mongoDB at ${mongoHostName}`);
});
});
実行あなたの
$ npm start
今行きましょうuser.controller.js
適用によってpassport-jwt
APIに.
パスポートJWTを登録/ログインAPIに適用します
イメージソース:dotnetトリック.コム
import express from 'express';
import jwt from 'jsonwebtoken';
import { validationResult } from 'express-validator';
import { config } from '../store/config';
import {
generateHashedPassword,
generateServerErrorCode,
registerValidation,
loginValidation,
} from '../store/utils';
import {
SOME_THING_WENT_WRONG,
USER_EXISTS_ALREADY,
WRONG_PASSWORD,
USER_DOES_NOT_EXIST,
} from '../store/constant';
import { User } from '../database/models';
const userController = express.Router();
const createUser = (email, password) => {
const data = {
email,
hashedPassword: generateHashedPassword(password),
};
return new User(data).save();
}
/**
* GET/
* retrieve and display all Users in the User Model
*/
userController.get('/', (req, res) => {
User.find({}, (err, result) => {
res.status(200).json({ data: result });
});
});
/**
* POST/
* Register a user
*/
userController.post('/register', registerValidation, async (req, res) => {
const errorsAfterValidation = validationResult(req);
if (!errorsAfterValidation.isEmpty()) {
return res.status(400).json({
code: 400,
errors: errorsAfterValidation.mapped(),
});
}
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
await createUser(email, password);
// Sign token
const newUser = await User.findOne({ email });
const token = jwt.sign({ email }, config.passport.secret, {
expiresIn: 10000000,
});
const userToReturn = { ...newUser.toJSON(), ...{ token } };
delete userToReturn.hashedPassword;
res.status(200).json(userToReturn);
} else {
generateServerErrorCode(res, 403, 'register email error', USER_EXISTS_ALREADY, 'email');
}
} catch (e) {
generateServerErrorCode(res, 500, e, SOME_THING_WENT_WRONG);
}
});
/**
* POST/
* Login a user
*/
userController.post('/login', loginValidation, (req, res) => {
const errorsAfterValidation = validationResult(req);
if (!errorsAfterValidation.isEmpty()) {
return res.status(400).json({
code: 400,
errors: errorsAfterValidation.mapped(),
});
}
const { email, password } = req.body;
const user = await User.findOne({ email });
if (user && user.email) {
const isPasswordMatched = user.comparePassword(password);
if (isPasswordMatched) {
// Sign token
const token = jwt.sign({ email }, config.passport.secret,
{
expiresIn: 1000000,
});
const userToReturn = { ...user.toJSON(), ...{ token } };
delete userToReturn.hashedPassword;
res.status(200).json(userToReturn);
} else {
generateServerErrorCode(res, 403, 'login password error', WRONG_PASSWORD, 'password');
}
} else {
generateServerErrorCode(res, 404, 'login email error', USER_DOES_NOT_EXIST, 'email');
}
});
export default userController;
$ npm start
イメージソース:dotnetトリック.コム
import express from 'express';
import jwt from 'jsonwebtoken';
import { validationResult } from 'express-validator';
import { config } from '../store/config';
import {
generateHashedPassword,
generateServerErrorCode,
registerValidation,
loginValidation,
} from '../store/utils';
import {
SOME_THING_WENT_WRONG,
USER_EXISTS_ALREADY,
WRONG_PASSWORD,
USER_DOES_NOT_EXIST,
} from '../store/constant';
import { User } from '../database/models';
const userController = express.Router();
const createUser = (email, password) => {
const data = {
email,
hashedPassword: generateHashedPassword(password),
};
return new User(data).save();
}
/**
* GET/
* retrieve and display all Users in the User Model
*/
userController.get('/', (req, res) => {
User.find({}, (err, result) => {
res.status(200).json({ data: result });
});
});
/**
* POST/
* Register a user
*/
userController.post('/register', registerValidation, async (req, res) => {
const errorsAfterValidation = validationResult(req);
if (!errorsAfterValidation.isEmpty()) {
return res.status(400).json({
code: 400,
errors: errorsAfterValidation.mapped(),
});
}
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
await createUser(email, password);
// Sign token
const newUser = await User.findOne({ email });
const token = jwt.sign({ email }, config.passport.secret, {
expiresIn: 10000000,
});
const userToReturn = { ...newUser.toJSON(), ...{ token } };
delete userToReturn.hashedPassword;
res.status(200).json(userToReturn);
} else {
generateServerErrorCode(res, 403, 'register email error', USER_EXISTS_ALREADY, 'email');
}
} catch (e) {
generateServerErrorCode(res, 500, e, SOME_THING_WENT_WRONG);
}
});
/**
* POST/
* Login a user
*/
userController.post('/login', loginValidation, (req, res) => {
const errorsAfterValidation = validationResult(req);
if (!errorsAfterValidation.isEmpty()) {
return res.status(400).json({
code: 400,
errors: errorsAfterValidation.mapped(),
});
}
const { email, password } = req.body;
const user = await User.findOne({ email });
if (user && user.email) {
const isPasswordMatched = user.comparePassword(password);
if (isPasswordMatched) {
// Sign token
const token = jwt.sign({ email }, config.passport.secret,
{
expiresIn: 1000000,
});
const userToReturn = { ...user.toJSON(), ...{ token } };
delete userToReturn.hashedPassword;
res.status(200).json(userToReturn);
} else {
generateServerErrorCode(res, 403, 'login password error', WRONG_PASSWORD, 'password');
}
} else {
generateServerErrorCode(res, 404, 'login email error', USER_DOES_NOT_EXIST, 'email');
}
});
export default userController;
テスト
POST/
メソッドと入力localhost:8080/register
and localhost:8080/login
. register api成功したトークンとユーザのメールを返します.
認可
ログインするユーザーが必要な特定のリンクに移動したい場合は、見てみましょう.それから、あなたは単にAPIで承認を加えることができます.
例を見てみましょう.
user.controller.js
, シンプルに含める'/'
すべてのユーザのリストを取得するAPI — しかし、私はユーザとしてログインしない限り、すべてのユーザーを取得したくありません.PHP APIに接続されていないJWTの例
パスポートでの認可
これらのハイライトをあなたに加えてくださいuser.controller.js
:
import express from 'express';
import jwt from 'jsonwebtoken';
import passport from 'passport';
import { validationResult } from 'express-validator';
...
/**
* GET/
* retrieve and display all Users in the User Model
*/
userController.get(
'/',
**passport.authenticate('jwt', { session: false }),**
(req, res) => {
User.find({}, (err, result) => {
res.status(200).json({ data: result });
});
}
);
...
export default userController;
さて、PostmanでAPIをテストします.「承認」をクリックして、タイプ「Bearerトークン」を選んでください次にトークンをトークンフィールドにペーストして実行します.
JWTを使用すると、すべてのユーザーを取得することができます
よくできた!
あなたは今、APIを使用する前にログインするユーザーを必要とする他のすべてのルートを承認し、安全にすることができます.
import express from 'express';
import jwt from 'jsonwebtoken';
import passport from 'passport';
import { validationResult } from 'express-validator';
...
/**
* GET/
* retrieve and display all Users in the User Model
*/
userController.get(
'/',
**passport.authenticate('jwt', { session: false }),**
(req, res) => {
User.find({}, (err, result) => {
res.status(200).json({ data: result });
});
}
);
...
export default userController;
あなたは今、APIを使用する前にログインするユーザーを必要とする他のすべてのルートを承認し、安全にすることができます.
Reference
この問題について(一歩一歩、ノードを設定するガイドです.パスポートJWTとのJS API), 我々は、より多くの情報をここで見つけました https://dev.to/calvinqc/a-step-by-step-guide-to-setting-up-a-node-js-api-with-passport-jwt-5fa5テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol