[ λ νκ° ] ν κΆμΌλ‘ λλ΄λ Node & Express 2νμ μ½κ³ ...
π [ λ νκ° ] Web Development with Node & Express 2νμ μ½κ³ ...
βοΈ μλ‘
μ΄ μ±
μ λ³΄κ² λ κ³κΈ°λ μλ¦¬μ€ ν νλ‘μ νΈμμ νλ‘ νΈμλλ₯Ό μ€λΉνκ³ μλ λμκ² λ¬΄μ§νλ λ°±μλ ννΈλ₯Ό λ΄λΉνκ² λμκ³ , 맨λ
μ ν€λ©νλ 격μΌλ‘ λ°±μλμ κ΄ν μ 보λ₯Ό μ΄λ¦¬μ 리 μ°Ύμ보λ μ€ λΉκ΅μ μ΅κ·Ό(2021.5.21.
)μ μΆννκ³ Spring
μ λ€λ£¨λ μ±
μ΄ μλλΌ Express.js
λ₯Ό λ€λ£¨λ μμ μ΄μ΄μ ꡬ맀νλ€. μ±
μ μλΌλμμ μ£Όλ¬Ένκ³ , μ±
μ μ½ 450νμ΄μ§λ‘ ꡬμ±λμ΄μμΌλ©° λ
μκΈ°κ°μ 2022.01.25 ~ 2022.02.19
μ΄λ€.
βοΈ λ³Έλ‘
ννμ΄ μ±
μ μ½μΌλ©° λΉμ₯μ λ°±μλλ₯Ό ꡬνν΄μΌνλν°λΌ λ΄κ° νμν μ£Όμ λ§ λ¨Όμ μ΄ν΄λ΄€λ€. μ΅μ€νλ μ€ μκ°, νμ§λ³΄μ¦, μΏ ν€μ μΈμ
, λ―Έλ€μ¨μ΄, μ§μμ±, λΌμ°ν
, REST APIμ JSON, SPA, 보μ ννΈμλ€. μ΄ μ€μμ κ°μ₯ κΈ°μ΅μ λ¨λ λΆλΆμ λ°λ‘ λ―Έλ€μ¨μ΄, μΏ ν€μ μΈμ
μΈλ°, λλ JWT
λ₯Ό μ΄μ©νμ¬ μΈμ¦μ ꡬννμ§λ§ μλ²μμ μΏ ν€λ₯Ό μ ν μΈμνμ§ λͺ»νλ λ¬Έμ κ° μμλλ° κ²°κ΅ cookie-parser
λ―Έλ€μ¨μ΄λ₯Ό μμ±νμ§ μμμ μκΈ°λ λ¬Έμ μλ€.. (μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ½ 3μκ°μ μ½μ§νλ€.) λλΆμ λ―Έλ€μ¨μ΄μ μ€μμ±μ κΉ¨λ¬μλ€. κ·Έλ¦¬κ³ μΏ ν€μ λν΄ κΈ°μ‘΄μ μκ³ μλ μ§μκ³Ό λλΆμ΄ λͺ κ°μ§ μλ‘μ΄ μ¬μ€μ μκ² λμλλ°, μΏ ν€μ κ΄ν΄ μμλ¬μΌ ν μ€μν λ΄μ©μ λ€μκ³Ό κ°λ€.
1. μ¬μ©μκ° μΏ ν€ λ΄μ©μ λ³Ό μ μλ€.
- μλ²μμ ν΄λΌμ΄μΈνΈμ 보λ΄λ μΏ ν€λ λͺ¨λ ν΄λΌμ΄μΈνΈμμ λ³Ό μ μλ€. μΏ ν€λ₯Ό μνΈνν΄μ μ½ν
μΈ λ₯Ό 보νΈν μ μκΈ΄ νμ§λ§, λ³λ³ν λͺ©μ μΌλ‘λ§ μ¬μ©νλ€λ©΄ κ΅³μ΄ μνΈνν μ΄μ κ° μλ€. μλͺ
λ (Signed)μΏ ν€λ μ½ν
μΈ λ₯Ό μ½κΈ° μ΄λ ΅κ² λ§λ€κΈ΄ νκ² μ§λ§, μνΈνλΌκ³ ν μ μλ μμ€μ΄ μλλ€.
2. μ¬μ©μκ° μΏ ν€λ₯Ό μμ νκ±°λ κΈμ§ν μ μλ€.
- μ¬μ©μλ μΏ ν€ μ 체μ λν κΆνμ΄ μκ³ , λΈλΌμ°μ μλ μΏ ν€λ₯Ό κ°λ³μ μΌλ‘, λλ νκΊΌλ²μ μμ νλ κΈ°λ₯μ΄ μλ€. λν, μ¬μ©μκ° μΏ ν€λ₯Ό κΈμ§ν μλ μλλ° μ΄λ΄ λ μΏ ν€ μμ΄λ μ λλ‘ λμν μ μλ μΉ μ ν리μΌμ΄μ
μ μ λ§ λ¨μν κΈ°λ₯ λ§κ³ λ μννκΈ° μ΄λ ΅λ€.
3. μΏ ν€λ 곡격μ μ¬μ©λ μ μλ€.
- XSS(cross-site-scripting attack) 곡격 μ€ μ
μμ μΈ μλ°μ€ν¬λ¦½νΈ μ½λλ‘ μΏ ν€ μ½ν
μΈ λ₯Ό λ°κΎΈλ λ°©λ²λ μλ€. μλ²μ μ μλλ μΏ ν€λ₯Ό λ§Ήμ ν΄μλ μ λλ μ΄μ μ€ νλλ€. `μλͺ
λ μΏ ν€(Signed cookie)`λ₯Ό μ¬μ©νλ©΄ μ¬μ©μλ μλ°μ€ν¬λ¦½νΈ μ½λλ‘ μΏ ν€λ₯Ό λ³μ‘°νμ κ²½μ° κ·Έ νμ μ΄ λͺ
λ°±ν λλ¬λλ―λ‘ κ³΅κ²©μ λ§λλ° λμμ΄ λλ€. (μλͺ
λ μΏ ν€λ μΌλ°μ μΈ μΏ ν€λ³΄λ€ μ°μ μμκ° λλ€. μλͺ
λ μΏ ν€μμ μ¬μ©λ μ΄λ¦μ μΌλ° μΏ ν€μμλ μ¬μ©ν μ μλ€.) λλ `httpOnly` μ΅μ
μ μ¬μ©νμ¬ ν΄λΌμ΄μΈνΈμμ μΏ ν€λ₯Ό μμ νμ§ λͺ»νκ³ μλ²μμλ§ κ°λ₯νκ²λ μ€μ ν μλ μλ€. μ΄λ° κ²½μ° νμ©λκ° μ‘°κΈ λ¨μ΄μ§μ§λ§ ν¨μ¬ μμ νλ€.
4. μΏ ν€λ₯Ό λ¨μ©νλ©΄ μ¬μ©μκ° λμΉμ±λ€.
- μ¬μ©μμ μ»΄ν¨ν°μ μΏ ν€λ λ°μ΄ν°λ₯Ό λ무 λ§μ΄ μ μ₯νλ©΄ μ¬μ©μλ₯Ό μ§μ¦λκ² ν μ μμΌλ―λ‘ νΌν΄μΌ νλ€. μΏ ν€λ μ΅μνμΌλ‘ μ μ§ν΄λΌ.
5. μΏ ν€μμ μ¬μ© ν μ μλ option
- domain: μΏ ν€μ λλ©μΈμ μ°κ²°νλ€. νμ§λ§ νμ¬ μλ²κ° μ€ν μ€μΈ λλ©μΈμ΄ μλ λ€λ₯Έ λλ©μΈκ³Ό μ°κ²°ν μλ μλ€.
- path: μΏ ν€κ° μ μ©λ κ²½λ‘λ₯Ό μ§μ νλ€. κΈ°λ³Έκ°μΈ `/`λ₯Ό μ¬μ©νλ©΄ μ¬μ΄νΈμ λͺ¨λ νμ΄μ§μ μΏ ν€κ° μ μ©λλ€. κ²½λ‘λ₯Ό `/foo`λ‘ μ€μ νλ©΄ `/foo`, `/foo/bar` λ±μ μ μ©λλ€.
- maxAge: ν΄λΌμ΄μΈνΈκ° μΏ ν€λ₯Ό μΌλ§λ μ€λ 보κ΄νκ³ μμ΄μΌ νλμ§ λ°λ¦¬μ΄ λ¨μλ‘ μ§μ νλ€. μ΄ μ΅μ
μ μ€μ νμ§ μμΌλ©΄ μΏ ν€λ λΈλΌμ°μ λ₯Ό λ«μ λ μμ λλ€. `expired` μ΅μ
μμ λ§λ£ λ μ§λ₯Ό μ€μ ν μλ μμ§λ§ λ¬Έλ²μ΄ 볡μ‘νκΈ° λλ¬Έμ `maxAge`λ₯Ό κΆνλ€.
- secure: `HTTPS` μ°κ²°μ ν΅ν΄μλ§ μΏ ν€λ₯Ό μ μ‘νλ€.
- httpOnly: μλ²μμλ§ μΏ ν€λ₯Ό μμ νλ€. μ¦, clientμμλ μΏ λ¦¬λ₯Ό μμ ν μ μλ€. XSS곡격μ λ§λλ° λμμ΄ λλ€.
- signed: μΏ ν€μ μλͺ
μ ν΄μ `res.cookie`κ° μλλΌ `res.signedCookies`μμ μ κ·Όν μ μκ² νλ€. μλͺ
λ μΏ ν€κ° λ³μ‘°λλ©΄ μλ²λ κ·Έ μΏ ν€λ₯Ό κ±°λΆνκ³ μλ κ°μΌλ‘ μ΄κΈ°ν νλ€.
λν, passport
λ₯Ό μ΄μ©ν΄ μΈμ¦ννΈλ₯Ό ꡬννλλ°, GitHub Strategy
λ₯Ό μ¬μ©ν΄μ λ€μκ³Ό κ°μ΄ μΈμ¦μ ꡬννλ€. μ²μμλ passport
ννμ΄μ§μ docsμ λΉμ·νκ² μμ±νμ§λ§, λ€μ μ½λλ λ΄κ° GitFarm
νλ‘μ νΈμμ μμ±ν λ°±μλ μ½λμ΄λ€. μ½λλ 짧μ 보μ΄μ§λ§ λμ μλΉμ€μ νμν μ 보μ λ§κ² μμ νλλ° κ·Έ μμ
μ΄ μκ°λ³΄λ€ μ€λ κ±Έλ Έλ€.
// passport/strategy/GitHub.js
import GitHub from "passport-github2";
import keys from "../../config/keys.js";
import { User } from "../../model/index.js";
const GitHubStrategy = GitHub.Strategy;
const { clientID, clientSecret, callbackURL } = keys.GitHub;
const config = {
clientID,
clientSecret,
callbackURL,
};
export default new GitHubStrategy(
config,
async (accessToken, refreshToken, profile, done) => {
const { username } = profile;
const { id, avatar_url: avatarUrl } = profile._json;
const findUser = await User.findOne({ id });
if (!findUser) {
const newUser = new User({
id,
username,
avatarUrl,
accessToken,
});
newUser.save();
return done(null, newUser);
}
return done(null, findUser);
},
);
// routes/api/auth.js
router.get(
"/github",
passport.authenticate("github", {
scope: ["repo", "profile", "user"],
session: false,
}),
);
router.get(
"/github/callback",
passport.authenticate("github", {
session: false,
failureRedirect: "/api/auth/login/failed",
}),
async (req, res) => {
const { id, username } = req.user;
const payload = { id, username };
const token = await createToken(payload);
res.cookie("token", token, cookieConfig);
res.redirect("/loading");
},
);
βοΈ κ²°λ‘
μ΄ μ±
μ μ½μΌλ©° μ΅μνμ λ°±μλμμ νμν μ½λλ₯Ό μμ±νλλ° λμμ λ§μ΄ λ°μλ€. μμ§κΉμ§ μ°λ¦¬λλΌμμλ Express.js
λ³΄λ€ Spring
μ λ λ§μ΄ μ¬μ©νμ§λ§, λ°±μλμ ν° νμ λ²μ΄λμ§ μμ κ²μ΄λ€. JAVA
λ³΄λ€ JS
λ₯Ό λ μ μλ©΄μ λ°±μλλ₯Ό λ§λ³΄κ³ μΆμ λΆλ€μκ² μΆμ²ν΄μ£Όκ³ μΆμ μ±
μ΄λ€.
reference