엑세스 해싱
정확히 무슨기능을 만드는지 인식하고 들어가는게 중요하다.
회원가입을 진행하면 비밀번호를 해싱해서 저장하는것.
비밀번호 탈취시에도 뚫리는시간을 오래걸리게끔 방지한다.
과정에서 암호화하는데 두가지 방법이있다.
하나는 내부 모듈 crypto
다른 하나는 외부 모듈 bcrypt
bcrypt
//express path mysql ejs
const express= require("express");
const path= require("path");
const mysql2=require("mysql2/promise");
const ejs= require("ejs");
const joinRouter=require("./routers/joinrouter");
const loginRouter=require("./routers/loginrouter");
const app=express();
app.set("views",path.join(__dirname,"page"));
app.set("view engine","ejs");
app.use(express.urlencoded({extended:false}));
app.use('/join',joinRouter);
app.use('/login',loginRouter);
app.listen(8000,()=>{
console.log("server on");
})
가장 기본적 준비과정 page사용을 위해 연결해주고 express 객체의 옵션을 설정해준다,
깊은 객체를 사용하지않고 req.body를 사용하기위해
app.use(express.urlencoded({extended:false})); extended :false 옵션을 사용하고
app.use를 통해 미들웨어에 경로를 추가함으로 ‘/login’ 주소를 받게되면 그이후에 들어오게되는 주소를 실행토록한다.
const joinRouter=require("./routers/joinrouter");
예를 들어 ‘/join/’ 이 미들웨어에 추가되어있다면 뒤에있는 경로 즉 routers/joinroute에서 이후의 라우팅을 진행해준다 따라서 joinrouter의 루트 주소로 가게된다. ‘/’ 물론 현재 주소차엥는 /join/ 이런식으로 표시되어있을것이다.
const router=require("express").Router();
const {SignUp} =require("../controllers/userscontroller");
router.get('/',(req,res)=>{
res.render("join");
})
//함수도 값으로 익명함수자리에 들어가서 사용가능
router.post('/',SignUp);
module.exports=router;
router 부터 코드 리뷰하자면 express 객체의 router메서드를 실행한뒤 router에 선언해준다.
{SignUp} = 구조분해 할당으로 ../controllers/userscontroller 에서 객체로 모듈을 받아온다음 같은 이름 Signup 으로 선언한것이다.
router.get('/',(req,res)=>{ res.render("join"); })
get이하의 주소 ‘/’로가면 express 에서 req,res를 반환해주고 res.render(”join”) page폴더의 join.ejs를 그려주게된다.
router.post('/',SignUp);
router.post는메서드 주소 ‘/’ 이하에서 post요청이 들어오면 처리해주게된다.
원래는 get 메서드를 통해 req,res에 반환해주는것처럼 익명함수를 통해 그값을 다시 컨트롤러의 값에 반환해주곤했지만 .
컨트롤러에서 바당온 함수는 어차피 req,res를 매개변수로 받기에 이를 감안해 함수를 값으로 받아와 익명함수자리 대신에 바로 사용하게된다.
module.exports=router; 는 router 개체를 뿜어주는것이다.
자연스럽게 SignUp함수를 리뷰해보겠다. 컨트롤러에서 import되어 익명함수대신에 바로 사용된것이니만큼 코드의 실제 위치는
userscontroller.js 에 존재한다. 엥 코드 signup리뷰한다고하고 login함 아무튼
exports.Login= async (req,res)=>{
const {user_id,user_pw}=req.body;
try {
const data = await userSelect(user_id);
if(!data?.user_id)
{
return res.send("아이디없음");
}
const compare_pw= await compare(user_pw,data.user_pw); // true false값 반환
if(compare_pw){
return res.send("비밀번호 틀림");
}
res.send("로그인됨")
} catch (err) {
console.log(err);
}
}
상기코드의 내용은 다음과같다.
화면단에서 express router를 통해 받아온 req,res 는 req.body에서 구조 분해할당을 통해
const {user_id,user_pw}=req.body;
user_id,user_pw를 뽑아주게된다,
await userSelect (user_id ) 이 코드는
async()=(user_id)⇒{
mysql.query(”SELECT * FROM user WHERE user_id=?”,[user_id])
} 아래와 같은 형태를 가지며 데이터베이스에서 아이디에 해당하는 행에대한 정보를 다가지고올것이다.
id필드는 기본적으로 부여되는 고유 숫자라 유저는 알길이 없고 비밀번호는 해싱을 통해 암호화되어있기때문에 관리자 역시 유저의 입력없이는 접근하기 힘들다.
const compare_pw= await compare(user_pw,data.user_pw); // true false값 반환
는 화면단에서 받아온 user_pw 와 db에서 받아온 data 즉해싱된 비밀번호를 비교할수있게해준다.
만약 두값이 같다면 compare 함수에서 생성된 promise 객체에서 resolve(same) 즉 true를 반환한다.
다를경우 반환하는것은없다.
trycatch 문을통해서 오류가 나도 멈추지않게 방지해준다. 다만 err을 찍어준다.
if(!data?.user_id)
옵션체이닝도 중요하지만 말이다
원래 정리하려고한
signup그리고 userInsert 에 대해 정리해볼까한다.
SignUp
exports.SignUp=async (req,res)=>{
const {user_id,user_pw} =req.body;
try {
const hash= await createHash(user_pw);
await userInsert(user_id,hash);
res.redirect('/login');
} catch (error) {
console.log(error);
}
router에서는 분명 router.post(’/’,Signup) 함수값을 넘겨주어 바로 넣어서 사용해줄걸이다.
router에서 해당 주소로간뒤 실행되는 저함수는
.SignUp=async (req,res)=>{ const {user_id,user_pw} =req.body
async 함수로 비동기를 지원하며 화면단에서 받아온 input (name) 의값을 req.body안에 가지고있고
그값을 구조분해할당으로 user_id, user_pw로 뿜어주게된다.
그후 trycatch문을통해 err발생하더라도 서버가 멈추지않게 해준다.
const hash = await createHash(user_pw)는 받아온 유저 비밀번호를 model 폴더의 createHash를통해 해싱해주고 그값을 반환하게되는 여기서 해싱하는 방법이 두가지 존재한다.
첫번째는 bcrypt 모듈의 함수를 통해서 손쉽게 만드는것이다. 특징적인것으로는 스트레칭 2의 n승으로 설정해주는것이고 보통은 10으로 설정해준다 그이상으로 늘어나게되면 시간이 오래걸리기때문이다.
createHash 함수는 화살표 연산자로 (passoword)⇒ return new Promise를 통해 비동기적으로 결과를 관리해준다. 그 코드가 아래에있당.
return new Promise((resolve,reject)=>{
// hash 메서드로 해시값을 만들어줄수잇다.
// 비밀번호 스트레칭 콜백함수 문자열?
bcrypt.hash(password,10,(err,data)=>{
if(err)reject(err)
resolve(data);
const createHash=(password)=>{
return new Promise((resolve,reject)=>{
// hash 메서드로 해시값을 만들어줄수잇다.
// 비밀번호 스트레칭 콜백함수 문자열?
bcrypt.hash(password,10,(err,data)=>{
if(err)reject(err)
resolve(data);
});
})
}
두번째 방법은
비동기식 처리의 핵심키워드에 들어가는 Promise resolve reject async await. 을 이해하고 가는것이 훨씬 중요하다.
핵심은 아래 글에 있는 요약에 적혀있는 바와 같이 promise 객체는 resolve와 reject를 통해서 결과를 관리하는 방법을 제공한다는면에서 중요하고
async await은 동기코드처럼 처리하고 읽기 쉽고 간결하다는점에서 장점을 가진다
Promise, resolve, reject, async 및 await는 모두 비동기 작업을 처리하기 위해 JavaScript에서 사용되는 개념 및 키워드입니다. 각각에 대한 간략한 설명은 다음과 같습니다.
- 약속: 약속은 JavaScript에서 비동기 작업을 처리하는 방법입니다. 비동기 작업의 미래 가치 또는 최종 완료(또는 실패)를 나타냅니다. Promise에는 fulfilled(해결됨) 또는 rejected의 두 가지 가능한 상태가 있습니다. 콜백에 비해 비동기 코드를 처리하는 더 깔끔하고 구조화된 방법을 제공합니다.
- resolve: resolve는 약속을 값으로 이행하는 데 사용되는 약속에서 제공하는 기능입니다. 일반적으로 비동기 작업이 성공하면 Promise의 실행기 함수 내에서 호출됩니다.
- reject: reject는 이유 또는 오류가 있는 Promise를 거부하는 데 사용되는 Promise에서 제공하는 기능입니다. 일반적으로 비동기 작업에서 오류가 발생하거나 실패할 때 Promise의 실행기 함수 내에서 호출됩니다.
- async 및 await: async 및 await는 ES2017(ES8)에서 약속 작업을 위한 구문 설탕으로 도입된 키워드입니다. async 키워드는 비동기 함수를 정의하는 데 사용되며 함수가 본문 내에서 await 키워드를 사용할 수 있도록 합니다. 'await' 키워드는 Promise가 이행되거나 거부될 때까지 비동기 함수의 실행을 일시 중지하는 데 사용됩니다. 보다 동기식 스타일로 작성할 수 있도록 하여 비동기 코드를 단순화합니다.
요약하면 Promise는 비동기 작업을 처리하고 resolve 및 reject를 사용하여 결과를 관리하는 방법을 제공합니다. 'async' 및 'await'는 Promise와 함께 작업하여 비동기 코드를 작성하는 더 간결하고 읽기 쉬운 방법을 제공하는 JavaScript의 최신 추가 기능입니다.
참고한
https://inpa.tistory.com/entry/EXPRESS-📚-요청-객체와-응답-객체-req-res
'backend > nodejs' 카테고리의 다른 글
| 20230508 nodejs 미들웨어 등 (0) | 2023.09.07 |
|---|---|
| 20230504 nodejs express ejs mysql2 path (0) | 2023.09.07 |
| 20230501 (0) | 2023.07.26 |
| 20230428 # TCP와 UDP ,서버 (0) | 2023.07.25 |
| 20230427 nodejs시작 (0) | 2023.07.25 |