노드의 단계별 안내서를 설정합니다.js API 및 Passport JWT
인증과 권한 수여는 응용 프로그램의 중요한 구성 부분이다.보호나 검사가 없는 API 루트가 존재하면 응용 프로그램은 해커의 목표가 되기 쉽다.이것이 바로 우리가 왜 안전 팻말을 필요로 하는가 하는 것이다 — JSON Web Token (JWT).
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 웹 영패는 사용자의 정보를 인코딩하고 디코딩합니다.그것들은 권한 수여와 정보 교환에 사용된다.
그것들은 세 부분으로 구성되어 있다 — 제목, 유효 하중 및 서명 — 점(.
으로 구분: xxxxx.yyyyy.zzzzz
JSON 웹 토큰에 대한 자세한 내용 here 을 참조하십시오.
시작하기 전에
나는 너의 컴퓨터에 이미 npm와 테스트와 우편배달원이 있다고 가정한다. 만약 이것을 검사하지 않았다면.
이것은 code입니다. 만약 당신이 이 과정에서 어떤 문제가 있다면, 만약 당신이 어떤 문제를 물어볼 필요가 있다면, 트리빈slack에 가입하십시오.
서버 설정
자신의 서버를 사용하는 것을 좋아한다면 이 절차를 건너뛰십시오.
항목이 없으면 Trivin 를 사용하여 프로젝트 템플릿을 설정합니다.본고에서, 우리는 그것을 사용하여 간단한 노드 서버를 만들 것이다.
$ npm i trivin -g
$ trivin server simple-node-server -g -i
이렇게 하면 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
상수회사 명
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와 테스트와 우편배달원이 있다고 가정한다. 만약 이것을 검사하지 않았다면.
이것은 code입니다. 만약 당신이 이 과정에서 어떤 문제가 있다면, 만약 당신이 어떤 문제를 물어볼 필요가 있다면, 트리빈slack에 가입하십시오.
서버 설정
자신의 서버를 사용하는 것을 좋아한다면 이 절차를 건너뛰십시오.
항목이 없으면 Trivin 를 사용하여 프로젝트 템플릿을 설정합니다.본고에서, 우리는 그것을 사용하여 간단한 노드 서버를 만들 것이다.
$ npm i trivin -g
$ trivin server simple-node-server -g -i
이렇게 하면 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
상수회사 명
$ 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
문자열의 맞춤법 오류를 자동으로 완성하고 줄일 수 있습니다.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';
상수회사 명
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 설정
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);
});
})
);
};
utils.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';
수정store/passport.js
을passport와 함께 사용합니다.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
이제 과거로 돌아가 API에 store/config.js
를 적용하여 개선합시다 app.js
.
등록/로그인 API에 Passport jwt 적용
이미지 출처: dotnettricks.일반 도메인 이름 형식
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
이미지 출처: dotnettricks.일반 도메인 이름 형식
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;
테스트
user.controller.js
및passport-jwt
을 입력합니다.등록 API가 토큰과 사용자의 전자 메일 +id를 반환했습니다.
승인
사용자 로그인이 필요한 특정 링크로 이동하는지 살펴보겠습니다.그리고 간단하게 API에 라이센스를 추가할 수 있습니다.
우리 예를 하나 봅시다.
POST/
에는 모든 사용자의 목록을 검색하는 간단한 localhost:8080/register
API가 포함되어 있습니다. — 나는 사용자 신분으로 로그인하지 않는 한 모든 사용자를 검색하고 싶지 않다.API가 연결되지 않은 JWT의 예
JWT 여권 승인
이 하이라이트를 추가합니다localhost:8080/login
.
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를 테스트합니다.권한 부여를 클릭한 다음 유형 적재 영패 선택그런 다음 영패 필드에 영패를 붙여넣고 실행합니다.
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
이 문제에 관하여(노드의 단계별 안내서를 설정합니다.js API 및 Passport JWT), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 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.)