반응형
비밀번호가지고 로그인
- password : 로그인 인증할 때의 사용자가 입력한 비밀번호
- userSalt : DB에 저장되어있는 사용자의 salt
- userPassword : DB에 저장되어있는 사용자의 암호화된 비밀번호(해시 값)
단방향 암호화이므로 복호화를 할 수 없다. 따라서 비밀번호 암호화했을 때의 비밀번호와 salt를 가지고 동일한 방법으로 암호화를 진행하여 나온 값과 비교한다. 이때 salt는 비밀번호를 생성했을 때의 값과 똑같은 값을 사용해야 한다. 그렇지 않으면 일치하지 않는다.
만약 일치한다면 true, 일치하지 않는다면 false를 반환하도록 한다.
최신 코드
export const verifyPassword = async (password, userSalt, userPassword) => {
const key = await pbkdf2Promise(password, userSalt, 99999, 64, "sha512");
const hashedPassword = key.toString("base64");
if (hashedPassword === userPassword) return true;
return false;
};
이전 코드
let salt = Math.round(new Date().valueOf() * Math.random()) + "";
let password = req.body.password;
let hashPassword = crypto
.createHash("sha512")
.update(password + salt)
.digest("hex");
반응형
→ 내가 구글링할 때는 이전 코드로 해서 보안성이 조금 낮았다. 이전 코드에서 보면 알겠지만 오늘날짜로 해서 salt코드를 만들었다. 그리고 나서 해시알고리즘을 사용해주었지만, base64로 string하는 작업을 해주지 않았다. 그리고 암호화하여 코드 비교할 때도 작성을 안 해주어서 바꾸게 되었다.
나는 passport를 사용해서 비밀번호와 암호화된 비밀번호를 비교하여 이가 일치하면 로그인되는 방식을 구현하고자 하였다.
passport.use(
new LocalStrategy(
{
session: true, // 세션 저장 여부
usernameField: "id",
passwordField: "password",
},
async (id, password, done) => {
try {
// 회원정보 조회
const user = await models.Users.findOne({
where: {
join_id: id,
},
raw: true,
});
console.log("user :: ",user);
const pbkdf2Promise = util.promisify(crypto.pbkdf2);
let result = await models.Users.findOne({
attributes: ["salt", "password"],
where: {
join_id: id,
},
});
console.log("result :: ", result);
if (result !== null) {
console.log("salt :: ", result.dataValues.salt);
console.log("userPassword :: ", result.dataValues.password);
}
const userSalt = result.dataValues.salt;
const userPassword = result.dataValues.password;
async function verifyPassword(password, userSalt, userPassword) {
const key = await pbkdf2Promise(
password,
userSalt,
104906,
64,
"sha512"
);
const hashedPassword = key.toString("base64");
if (hashedPassword === userPassword) return true;
return false;
}
verifyPassword(password, userSalt, userPassword).then((answer) => {
console.log("answer :: ", answer);
});
const result_ans = await verifyPassword(
password,
userSalt,
userPassword
);
console.log("result_ans :: ", result_ans);
// 회원정보가 없거나 비밀번호가 일치하지 않는 경우
if (!user || !result_ans) {
done(null, false, {
message: "존재하지 않는 아이디이거나 비밀번호가 일치하지 않습니다.",
});
} else {
console.log("존재하는 아이디입니다.");
done(null, user); // serializeUser로 user 전달
}
} catch {
done(null, false, {
message: "서버에 문제가 발생했습니다. 잠시 후 다시 시도해 주세요.",
});
}
}
)
);
- passport에 로컬 전략을 사용하여 session에 저장되게 하였다. 그리고 아이디와 비밀번호를 프론트에서 가져왔다.
- 비동기 방식을 이용하여 구현하였다. 이는 util.promisify코드 때문이다. 이 코드는 비동기 방식으로 구현해서 await를 사용해서 도출해야 한다. 그렇지 않으면 코드가 실행이 안되었다. 이것때문에 promisify를 구현하고 싶은데 안되서 조금 헤맸다. 쓰니까 확실히 코드가 간결해지고 속도가 빠른 것 같다.
- crypto.pbkdf2는 crypto에 pbkdf2알고리즘이 있는데 여러 알고리즘이 있지만 이 방법을 요즘에 많이 쓰는 듯하다. 오래된 알고리즘은 해커들로 인하여 빨리 뚫리고 보안이 안 좋기 때문에 최신 동향의 알고리즘을 쓰는 것을 추천한다. 이를 사용하기 위해서는 db에 저장된 salt와 password를 가져와야 한다.
- 로그인에 쓴 비밀번호를 암호화시켜야 하는데 salt가 필요하다. 이를 가지고 비밀번호와 salt를 합쳐 해시알고리즘을 거치고 암호화를 시켰으면 db에 있는 비밀번호와 일치하는지 확인하는 작업을 해야 한다. 만약 같을 경우 세션에 저장해야 한다.
반응형