클라이언트 HTML, CSS는 FLORIN POP - DOUBLE SLIDER - SIGN IN/UP FORM 의 글을 보고 따라 했다.
실제 서비스는 여러 개의 데이터를 기입해야 하지만 지금은 가볍게 하기 위해 이메일, 비밀번호, 이름만 적게끔 했다.
간단하게 빈 값에 대한 validation을 한 후 ajax로 파리미터들을 전송하게 햇다.
서버에선 어떠케 처리를 하는지 코드를 적어 두자.
1 | // TODO: 가입 페이지 랜더링. |
security.csrfProtection(), {csrfToken: req.csrfToken()} 이 부분에 대해서 적을려고 한건데
저 코드가 사용된 이유는 csrf 라는 웹사이트 취약점 공격 중의 하나 인데(자세한 내용은 링크 참조) 대비책으로 사용하는 기법으로 자주 보는 npm 사이트에도 적용이 되어 잇다.
직접 만든 건 아니고 csurf라는 좋은 라이브러리가 잇어서 사용을 햇다.
이 기법이 쿠키 기반이라 cookie-parser가 필요함
이건 다음 글의 주제인 로그인에 대해 쓸 때 세션 때도 쓰므로 그 때 적어두자. 귀찮다..
위의 저 security.csrfProtection()의 코드를 보자.
1 | // TODO: csrf 검증. |
한 줄이면 끝. 이렇게 모듈로 만들어두고 쓰면 편리하더라. 나 같은 경우엔 html meta에 넣어두엇음.
새로 고침을 해 보면 이 토큰은 1회성 토큰이기 때문에 계속 바뀐다.
그리고 클라이언트에서 form이든 ajax든 서버에 데이터를 보낼 때 아래 처럼 저 토큰 값을 꼭 보내줘야 된다.
1 | const csrf = $('meta[name="csrf"]').attr('content'); |
이제 토큰 값과 함께 데이터를 보내면 서버에서 처리를 해야 한다.
1 | // TODO: 가입 처리. |
처리를 하는 라우터에 마찬가지로 security.csrfProtection()를 미들웨어로 넣으면
이 친구가 알아서 검증을 하기 때문에 정상 토큰 이면 다음으로 진행을 하고
비정상적인 토큰 값이거나 비어잇으면 403으로 리턴을 햇던 걸로..
사실 이건 회원 가입 뿐만 아니라 웹 사이트 전체 내에 사용자가 뭔가 입력을 하는 페이지의 같은 경우 다 넣어줘야 한다.
csrfProtection 코드를 모듈로 만든 이유가 이렇기 때문이다. 패시브처럼 써야 함.
나머지 가입 구현은 사실 위의 코드가 끝이다. 저 코드는 DB를 mongoDB를 쓰고 잇는데 클라가 보내준 email을 유저 컬렉션에서 조회를 한 후 중복된 이메일인지 체크를 해서 있으면 거절하고 업는 이메일이면 신규 유저로 인식을 하고 저장하는 게 끝이다.
저 코드에서 남겨둘려고 하는 건 xssFilter, changeHash 이 부분이다.
xss는 이거도 웹사이트 취약점 공격 중의 하나 인데(역시 이거도 자세한 내용은 링크 참조) 쉽게 적자면 사용자가 적는 form input에 스크립트를 넣는다는 소리다.
1 | <input name="aa" value="<script>alert('이게뭐여'</script>" |
뭐 이런식으로 해서 넘어올 때 스크립트가 만약에 잇다면 <> 이 부분만 entity 코드로 치환 해버리면 문자로 인식이 되기에 스크립트가 실행이 되질 않을 것이다.
1 | // TODO: 간단한 xss 필터. |
마지막으로 changeHash는 안전한 비밀번호 저장이란 글을 참고하면 좋다.
즉 비밀번호를 사용자가 입력한 일반 텍스트로 저장을 하면 안된다는 소리. 해킹은 고사하고 db 접근 권한이 잇는 사람이 들어가서 보면 그 사람이 평소에 쓰는 비밀번호나 이런 게 노출되버리기 때문이다. 악의적인 프로그래머라면 ㅎㅎ 말 안해도 끔찍하다.
아 여담으로 올해에 비밀번호를 평문으로 저장을 하는 코드와 DB를 난 본 적이 있다. 몹시 충격이였음…
1 | const crypto = require('crypto'); |
암튼 changeHash는 nodejs의 내장된 패키지인 crypto를 이용해 단방향 암호화 (=복호화가 안되는 암호화)로 변환을 하는 코드이다.
이걸 어떠케 사용하는거냐면
- 가입할 때 사용자가 비밀번호를 1q2w3e 뭐 이렇게 입력햇다고 치자.
- 서버에서 사용자가 보내준 비밀번호를 변환 -> 예로 7eb32f7589 뭐 이런 식으로 변환 된다.
- 가입을 할 때 저 변환된 값을 DB에 저장을 한다.
- 이제 사용자가 로그인 할 때 1q2w3e를 입력을 하면 서버에선 또 변환하여 DB에 저장된 변환된 비밀번호와 동일한지 체크를 하는 거다.
마지막으로 가입하는 짤 투척
가입은 이정도로 적어두고 다음 글에서 로그인, 소셜 로그인을 이어서 작성을 해야 겟다.
코드를 일부분만 적어 둿으므로 만약 만약에 누가 보게 될 경우엔 소스 코드를 참조 바랍니다.