216.73.216.168 TODAY : 3,339

PHP ์˜จ๋ผ์ธ ๊ฐ•์˜

 > 

PHP - ์ค‘๊ธ‰

๐Ÿ“š PHP ์ค‘๊ธ‰ - 1์ฃผ์ฐจ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ์ดˆ ๋ฐ MySQL ์—ฐ๋™ (PDO) - 04 SQL Injection ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ Prepared Statement

๐Ÿ“š PHP ์ค‘๊ธ‰ - 1์ฃผ์ฐจ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ์ดˆ ๋ฐ MySQL ์—ฐ๋™ (PDO) - 04 SQL Injection ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ Prepared Statement
ํ‰์  10.0 ๋ผ์ด์„ผ์Šค free
์‚ฌ์šฉ์žํ‰์  10.0 ์šด์˜์ฒด์ œ
๋‹ค์šด๋กœ๋“œ 1 ํŒŒ์ผํฌ๊ธฐ 0
์ œ์ž‘์‚ฌ LUZENSOFT ๋“ฑ๋ก์ผ 2025-07-12 12:38:25
์กฐํšŒ์ˆ˜ 39
- ์„ค๋ช…

๐Ÿ“š PHP ์ค‘๊ธ‰ - 1์ฃผ์ฐจ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ์ดˆ ๋ฐ MySQL ์—ฐ๋™ (PDO) - 04 SQL Injection ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ Prepared Statement







#SQL ์ธ์ ์…˜(Injection)์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

uploadImage



์•ˆ๋…•ํ•˜์„ธ์š”! #PHP ์ค‘๊ธ‰ ๊ณผ์ •์˜ ๋„ค ๋ฒˆ์งธ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ง€๋‚œ ์‹œ๊ฐ„์—๋Š” #PDO๋ฅผ ์ด์šฉํ•œ #๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค #์—ฐ๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ดค์ฃ . ์˜ค๋Š˜์€ ์›น #๋ณด์•ˆ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ณ  ๊ธฐ๋ณธ์ ์ธ ๋ถ€๋ถ„์ธ #SQL #์ธ์ ์…˜์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ณ , ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๊ธฐ์ˆ ์ธ #Prepared #Statement์— ๋Œ€ํ•ด ํ•™์Šตํ•  ๊ฑฐ์˜ˆ์š”.



SQL ์ธ์ ์…˜์€ #์›น #์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ #๋ณด์•ˆ #์ทจ์•ฝ์ ์„ ์ด์šฉํ•œ ๊ณต๊ฒฉ ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž๋Š” ์›น ํŽ˜์ด์ง€์˜ ์ž…๋ ฅ ํ•„๋“œ(์˜ˆ: ๋กœ๊ทธ์ธ ํผ, ๊ฒ€์ƒ‰์ฐฝ)์— #์•…์˜์ ์ธ #SQL #์ฝ”๋“œ ์กฐ๊ฐ์„ ์‚ฝ์ž…ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐ์ž‘ํ•˜๊ฑฐ๋‚˜, #๋ฏผ๊ฐํ•œ #์ •๋ณด๋ฅผ #ํƒˆ์ทจํ•˜๊ฑฐ๋‚˜, ์‹ฌ์ง€์–ด #๋ฐ์ดํ„ฐ๋ฅผ #ํŒŒ๊ดดํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.



์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ๋กœ๊ทธ์ธํ•˜๋Š” ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ๋งŒ์•ฝ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ œ๋Œ€๋กœ ๊ฒ€์ฆํ•˜์ง€ ์•Š๊ณ  SQL ์ฟผ๋ฆฌ์— ๊ทธ๋Œ€๋กœ ์‚ฝ์ž…ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



์›๋ž˜ ์˜๋„๋œ ์ฟผ๋ฆฌ: SELECT * FROM users WHERE username = '์‚ฌ์šฉ์ž์ž…๋ ฅ_์•„์ด๋””' AND password = '์‚ฌ์šฉ์ž์ž…๋ ฅ_๋น„๋ฐ€๋ฒˆํ˜ธ'



๊ณต๊ฒฉ์ž๊ฐ€ ' OR '1'='1' --'๋ฅผ ์‚ฌ์šฉ์ž์ž…๋ ฅ_๋น„๋ฐ€๋ฒˆํ˜ธ์— ์‚ฝ์ž…ํ•  ๊ฒฝ์šฐ: SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1' --'



์œ„ ์ฟผ๋ฆฌ์—์„œ --๋Š” SQL์—์„œ ์ฃผ์„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด password = '' OR '1'='1' ๋ถ€๋ถ„์€ ํ•ญ์ƒ ์ฐธ(True)์ด ๋˜์–ด, ๊ณต๊ฒฉ์ž๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชฐ๋ผ๋„ admin ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋งค์šฐ ์œ„ํ—˜ํ•œ ๋ณด์•ˆ ๊ตฌ๋ฉ์ด ๋ฉ๋‹ˆ๋‹ค.





Prepared Statement๊ฐ€ SQL ์ธ์ ์…˜์„ ๋ง‰๋Š” ์›๋ฆฌ

uploadImage



#์ค€๋น„๋œ #๊ตฌ๋ฌธ(Prepared Statement)์€ SQL ์ธ์ ์…˜ ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฐ€์žฅ ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. PDO๋Š” Prepared Statement ๊ธฐ๋Šฅ์„ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.



Prepared Statement์˜ ์ž‘๋™ ์›๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ฟผ๋ฆฌ ๊ตฌ์กฐ์™€ ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ: SQL ์ฟผ๋ฆฌ์˜ ๊ตฌ์กฐ(ํ…œํ”Œ๋ฆฟ)์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ(๋งค๊ฐœ๋ณ€์ˆ˜)๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

    • ์˜ˆ: SELECT * FROM users WHERE username = :username AND password = :password

    • ์—ฌ๊ธฐ์„œ :username๊ณผ :password๋Š” #ํ”Œ๋ ˆ์ด์Šคํ™€๋”(placeholder)์ž…๋‹ˆ๋‹ค.

  2. ์ฟผ๋ฆฌ ์ปดํŒŒ์ผ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํ”Œ๋ ˆ์ด์Šคํ™€๋”๊ฐ€ ํฌํ•จ๋œ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋จผ์ € ๋ฐ›์•„์„œ ์ปดํŒŒ์ผ(์ค€๋น„)ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ๋Š” ์•„์ง ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋งŒ ํŒŒ์•…ํ•˜๊ณ  ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

  3. ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐ ์‹คํ–‰: ๋‚˜์ค‘์— ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณ„๋„๋กœ ์ „์†กํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ์ฟผ๋ฆฌ ๊ตฌ์กฐ์— '๋ฐ”์ธ๋”ฉ'ํ•˜์—ฌ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์ˆ˜ํ•œ ๋ฐ์ดํ„ฐ ๊ฐ’์œผ๋กœ๋งŒ ์ธ์‹ํ•˜๋ฉฐ, ์–ด๋–ค ๊ฒฝ์šฐ์—๋„ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ SQL ์ฝ”๋“œ๋กœ ํ•ด์„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.



์ด๋Ÿฌํ•œ ๋ถ„๋ฆฌ ๋•๋ถ„์—, ๊ณต๊ฒฉ์ž๊ฐ€ ์ž…๋ ฅ ํ•„๋“œ์— ์•„๋ฌด๋ฆฌ ์•…์˜์ ์ธ SQL ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•ด๋„, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ด๋ฅผ ๋‹จ์ˆœํžˆ ํ…์ŠคํŠธ ๊ฐ’์œผ๋กœ๋งŒ ์ธ์‹ํ•˜๊ณ  SQL ๋ช…๋ น์–ด๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.





#PDO๋ฅผ ์ด์šฉํ•œ Prepared Statement ์‚ฌ์šฉ๋ฒ•


uploadImage


PDO์—์„œ Prepared Statement๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘ ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: #์ค€๋น„(Prepare)์™€ #์‹คํ–‰(Execute).




1. #์ค€๋น„ (Prepare)




PDO ๊ฐ์ฒด์˜ prepare() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SQL ์ฟผ๋ฆฌ ํ…œํ”Œ๋ฆฟ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด๋ƒ…๋‹ˆ๋‹ค. prepare() ๋ฉ”์„œ๋“œ๋Š” PDOStatement ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.



ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์ด๋ฆ„ ์žˆ๋Š” ํ”Œ๋ ˆ์ด์Šคํ™€๋” (Named Placeholders): :์ปฌ๋Ÿผ๋ช… ๋˜๋Š” :๋ณ„์นญ๊ณผ ๊ฐ™์ด ์ฝœ๋ก (:) ๋’ค์— ์ด๋ฆ„์„ ๋ถ™์ž…๋‹ˆ๋‹ค. ๊ฐ€๋…์„ฑ์ด ์ข‹๊ณ , ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. (๊ถŒ์žฅ)

    PHP

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
    
  • ๋ฌผ์Œํ‘œ ํ”Œ๋ ˆ์ด์Šคํ™€๋” (Question Mark Placeholders): ?๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜ ์ˆœ์„œ์— ์˜์กดํ•˜๋ฏ€๋กœ ์ˆœ์„œ๊ฐ€ ๊ผฌ์ด์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    PHP

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
    




2. #๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (Bind Data)




PDOStatement ๊ฐ์ฒด์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ”Œ๋ ˆ์ด์Šคํ™€๋”์— ๋ฐ”์ธ๋”ฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • bindValue(placeholder, value, [data_type]):

    • ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ํ”Œ๋ ˆ์ด์Šคํ™€๋”์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ๋ฐ”์ธ๋”ฉํ•˜๋ฉด ๊ฐ’์ด ๊ณ ์ •๋ฉ๋‹ˆ๋‹ค.

    • data_type์€ PDO::PARAM_STR(๋ฌธ์ž์—ด), PDO::PARAM_INT(์ •์ˆ˜) ๋“ฑ์œผ๋กœ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒ๋žต ์‹œ PDO๊ฐ€ ์ž๋™์œผ๋กœ ์ถ”๋ก ํ•˜์ง€๋งŒ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

    PHP

    // ์ด๋ฆ„ ์žˆ๋Š” ํ”Œ๋ ˆ์ด์Šคํ™€๋”์˜ ๊ฒฝ์šฐ
    $stmt->bindValue(':username', $inputUsername, PDO::PARAM_STR);
    $stmt->bindValue(':password', $inputPassword, PDO::PARAM_STR);
    
    // ๋ฌผ์Œํ‘œ ํ”Œ๋ ˆ์ด์Šคํ™€๋”์˜ ๊ฒฝ์šฐ (1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ธ๋ฑ์Šค)
    $stmt->bindValue(1, $inputUsername, PDO::PARAM_STR);
    $stmt->bindValue(2, $inputPassword, PDO::PARAM_STR);
    
  • bindParam(placeholder, variable, [data_type]):

    • ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ณ€์ˆ˜ ์ฐธ์กฐ์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค. execute() ํ˜ธ์ถœ ์‹œ์ ์— ๋ณ€์ˆ˜์˜ ํ˜„์žฌ ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ ์ฟผ๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•  ๋•Œ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

    PHP

    $user = 'some_user';
    $pass = 'some_pass';
    $stmt->bindParam(':username', $user, PDO::PARAM_STR);
    $stmt->bindParam(':password', $pass, PDO::PARAM_STR);
    
    $stmt->execute(); // $user์™€ $pass์˜ ํ˜„์žฌ ๊ฐ’์ด ์‚ฌ์šฉ๋จ
    
    $user = 'another_user';
    $pass = 'another_pass';
    $stmt->execute(); // $user์™€ $pass์˜ ์ƒˆ๋กœ์šด ๊ฐ’์ด ์‚ฌ์šฉ๋จ
    




3. #์‹คํ–‰ (Execute)




๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ ํ›„, execute() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ค€๋น„๋œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • execute(): ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    PHP

    $stmt->execute();
    
  • execute(array $input_parameters): bindValue()๋‚˜ bindParam()์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , execute() ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๋กœ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์—ฌ ํ•œ ๋ฒˆ์— ๋ชจ๋“  ํ”Œ๋ ˆ์ด์Šคํ™€๋”์— ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์ด ๊ฐ€์žฅ ๊ฐ„๊ฒฐํ•˜๊ณ  ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

    PHP

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
    $stmt->execute([
        ':username' => $inputUsername,
        ':password' => $inputPassword
    ]);
    

    ๋ฌผ์Œํ‘œ ํ”Œ๋ ˆ์ด์Šคํ™€๋”์˜ ๊ฒฝ์šฐ, ๋ฐฐ์—ด์˜ ์ˆœ์„œ๋Œ€๋กœ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค.

    PHP

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
    $stmt->execute([$inputUsername, $inputPassword]);
    





#Prepared Statement ์‹ค์Šต ์˜ˆ์ œ


uploadImage


๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ฝ”๋“œ๋Š” ์ด์ „ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜๋ฉฐ, ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์˜ˆ์‹œ๋กœ Prepared Statement๋ฅผ ์ ์šฉํ•ด ๋ด…์‹œ๋‹ค.



PHP

<?php
// DB_Connect.php (์ด์ „ ํฌ์ŠคํŒ…์—์„œ ๋งŒ๋“  DB ์—ฐ๊ฒฐ ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•œ๋‹ค๊ณ  ๊ฐ€์ •)
require 'DB_Connect.php'; // $pdo ๊ฐ์ฒด๊ฐ€ ์—ฌ๊ธฐ์— ์ •์˜๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    if (empty($username) || empty($password)) {
        echo "์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชจ๋‘ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.". "<br>";
    } else {
        try {
            // 1. ์ฟผ๋ฆฌ ์ค€๋น„ (ํ”Œ๋ ˆ์ด์Šคํ™€๋” ์‚ฌ์šฉ)
            // SQL ์ธ์ ์…˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ง์ ‘ ์ฟผ๋ฆฌ์— ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
            $sql = "SELECT id, username FROM users WHERE username = :username AND password = :password";
            $stmt = $pdo->prepare($sql);

            // 2. ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐ ์‹คํ–‰
            // execute() ๋ฉ”์„œ๋“œ์— ๋ฐฐ์—ด๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ
            $stmt->execute([
                ':username' => $username,
                ':password' => $password // ์‹ค์ œ ์•ฑ์—์„œ๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•ด์‹ฑํ•ด์„œ ๋น„๊ตํ•ด์•ผ ํ•จ!
            ]);

            // 3. ๊ฒฐ๊ณผ ๊ฐ€์ ธ์˜ค๊ธฐ
            $user = $stmt->fetch();

            if ($user) {
                echo "๋กœ๊ทธ์ธ ์„ฑ๊ณต! ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค, " . htmlspecialchars($user['username']) . "!". "<br>";
                // ์„ธ์…˜ ์‹œ์ž‘ ๋ฐ ์‚ฌ์šฉ์ž ์ •๋ณด ์ €์žฅ ๋“ฑ์˜ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ
            } else {
                echo "๋กœ๊ทธ์ธ ์‹คํŒจ: ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.". "<br>";
            }

        } catch (PDOException $e) {
            echo "๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์˜ค๋ฅ˜: " . $e->getMessage(). "<br>";
            // ์‹ค์ œ ์„œ๋น„์Šค์—์„œ๋Š” ์˜ค๋ฅ˜๋ฅผ ๋กœ๊น…ํ•˜๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
        }
    }
}
?>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>๋กœ๊ทธ์ธ ์˜ˆ์ œ</title>
</head>
<body>
    <h2>๋กœ๊ทธ์ธ</h2>
    <form method="POST" action="">
        <label for="username">์‚ฌ์šฉ์ž ์ด๋ฆ„:</label><br>
        <input type="text" id="username" name="username" required><br><br>
        <label for="password">๋น„๋ฐ€๋ฒˆํ˜ธ:</label><br>
        <input type="password" id="password" name="password" required><br><br>
        <input type="submit" value="๋กœ๊ทธ์ธ">
    </form>
</body>
</html>



์ฐธ๊ณ : ์œ„ ์˜ˆ์ œ๋Š” ๋ณด์•ˆ ๊ฐ•ํ™”๋ฅผ ์œ„ํ•ด ์‹ค์ œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•ด์‹ฑํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ณ , ๋กœ๊ทธ์ธ ์‹œ์—๋„ ์ž…๋ ฅ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•ด์‹ฑํ•˜์—ฌ ๋น„๊ตํ•˜๋Š” ๊ณผ์ •์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. #password_hash()์™€ #password_verify() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ‘œ์ค€์ž…๋‹ˆ๋‹ค.





๊ฒฐ๋ก  ๋ฐ ๋‹ค์Œ ์ฃผ์ฐจ ์˜ˆ๊ณ 




์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” #SQL #์ธ์ ์…˜์˜ ์œ„ํ—˜์„ฑ์„ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ , ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ํ•„์ˆ˜์ ์ธ ๊ธฐ์ˆ ์ธ #Prepared #Statement์˜ ์›๋ฆฌ์™€ #PDO์—์„œ์˜ ์‚ฌ์šฉ๋ฒ•์„ ์ตํ˜”์Šต๋‹ˆ๋‹ค. #์ฟผ๋ฆฌ #๊ตฌ์กฐ์™€ #๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฒ˜๋ฆฌํ•จ์œผ๋กœ์จ, ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช…๋ น์–ด๋กœ ์˜ค์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ์›์ฒœ์ ์œผ๋กœ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.



Prepared Statement๋Š” PDO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ  ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ์—ฌ๋Ÿฌ๋ถ„์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ #๋ณด์•ˆ ์œ„ํ˜‘์œผ๋กœ๋ถ€ํ„ฐ ์ง€ํ‚ค๋Š” ์ฒซ๊ฑธ์Œ์ž…๋‹ˆ๋‹ค. ํ•ญ์ƒ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๋ฐ›๋Š” ๋ชจ๋“  SQL ์ฟผ๋ฆฌ์— Prepared Statement๋ฅผ ์ ์šฉํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด์„ธ์š”.