์›น์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ • ๊ด€๋ จ ํ—ˆ์œ„ ํ–‰์œ„ ๊ฐ์ง€ ๋ฐ ๋ฐฉ์ง€

์ด ๋ฌธ์„œ์—์„œ๋Š” reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ • ๊ด€๋ จ ์‚ฌ๊ธฐ ํ™œ๋™์„ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

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

  • ์˜์‹ฌ์Šค๋Ÿฌ์šด ํ™œ๋™
  • ํ™œ๋™์ด ๋น„์Šทํ•œ ๊ณ„์ •
  • ํŠน์ • ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ‘œ์‹œ๋œ ๊ธฐ๊ธฐ์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ ๋ฐ ์‚ฌ์ดํŠธ๋ณ„ ๋ชจ๋ธ์˜ ๋ถ„์„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์‚ฌ๊ธฐ ๊ณ„์ • ์ œํ•œ ๋˜๋Š” ์‚ฌ์šฉ ์ค‘์ง€
  • ๊ณ„์ • ํƒˆ์ทจ ์‹œ๋„ ๋ฐฉ์ง€
  • ์„ฑ๊ณต์ ์ธ ๊ณ„์ • ํƒˆ์ทจ๋กœ ์ธํ•œ ํ”ผํ•ด ์™„ํ™”
  • ์ ๋ฒ•ํ•œ ์‚ฌ์šฉ์ž ๊ณ„์ •์—์„œ ์ „์†ก๋œ ์š”์ฒญ์—๋งŒ ์•ก์„ธ์Šค ๊ถŒํ•œ ๋ถ€์—ฌ
  • ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๊ธฐ ์ค‘ ํ•˜๋‚˜์—์„œ ๋กœ๊ทธ์ธํ•˜๋Š” ์‚ฌ์šฉ์ž์˜ ๋ถˆํŽธ ๊ฒฝ๊ฐ

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

  1. reCAPTCHA ํ™˜๊ฒฝ์„ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
  2. ์ ์ˆ˜ ๊ธฐ๋ฐ˜ ์‚ฌ์ดํŠธ ํ‚ค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์˜ ์›นํŽ˜์ด์ง€ ๊ตฌ์„ฑ

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์˜ ํšจ๊ณผ์ ์ธ ๊ฐ์ง€๋ฅผ ์œ„ํ•ด์„œ๋Š” ๊ณ„์ • ํ™œ๋™์„ ํฌ๊ด„์ ์œผ๋กœ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์— ๊ณ„์ • ๊ด€๋ จ ํ™œ๋™ ์ œ๊ณต์„ ์‹œ์ž‘ํ•˜๊ณ  ์‚ฌ์ดํŠธ๋ณ„ ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ  ๊ฐœ์„ ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ˆ˜ํ‰ ์›๊ฒฉ ๋ถ„์„ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์‚ฌ์šฉ ์„ค์ •
  2. ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—… ๋ณด๊ณ 
  3. ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ ํ‰๊ฐ€
  4. ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์ดํŠธ๋ณ„ ๋ชจ๋ธ ์กฐ์ •

์ˆ˜ํ‰ ์›๊ฒฉ ๋ถ„์„ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์‚ฌ์šฉ ์„ค์ •

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ–ˆ๊ฑฐ๋‚˜ ๋กœ๊ทธ์ธํ•˜๋„๋ก ์œ ๋„๋˜๋Š”์ง€์™€ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ž‘์—…์— ๋Œ€ํ•œ ์™„์ „ํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์— ๋”ฐ๋ผ ์ˆ˜ํ‰ ์›๊ฒฉ ๋ถ„์„ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ˆ˜๋™ ์ˆ˜์ง‘์„ ์‚ฌ์šฉ ์„ค์ •ํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ์›Œํฌํ”Œ๋กœ์— ํฌํ•จ๋œ ๋ชจ๋“  ์›นํŽ˜์ด์ง€์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ด์ „์— ๋งŒ๋“  ์ ์ˆ˜ ๊ธฐ๋ฐ˜ ์‚ฌ์ดํŠธ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด์„œ reCAPTCHA JavaScript ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ๋Š” ์›นํŽ˜์ด์ง€์—์„œ reCAPTCHA JavaScript ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    <head>
    <script src="https://www.google.com/recaptcha/enterprise.js?render=KEY_ID"></script>
    ....
    </head>

์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—… ๋ณด๊ณ 

์˜์‹ฌ์Šค๋Ÿฌ์šด ํ™œ๋™ ํŒจํ„ด์„ ๊ฐ์ง€ํ•˜๊ณ  ์‚ฌ์ดํŠธ์—์„œ ์ผ๋ฐ˜์ ์ธ ํ™œ๋™ ํŒจํ„ด์„ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๋Š” ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—…์—์„œ grecaptcha.enterprise.execute()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์›นํŽ˜์ด์ง€์—์„œ ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—…์„ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€์ ์ธ ์‹ ํ˜ธ ์ˆ˜์ง‘์— ๋„์›€์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—…์„ ๋ณด๊ณ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ณด๊ณ ํ•˜๋ ค๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ž‘์—…์— ๋Œ€ํ•ด grecaptcha.enterprise.execute()์˜ action ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ์‚ฌ์šฉ์ž ์ž‘์—…์„ ๊ธฐ์ˆ ํ•˜๋Š” ์ž‘์—… ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

๋‹ค์Œ ํ‘œ์—์„œ๋Š” ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ž‘์—…์„ ๋ณด๊ณ ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ์ด๋ฆ„์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์ž‘์—… ์ด๋ฆ„ ์‚ฌ์šฉ์ž ์‹œ์ž‘ ์ด๋ฒคํŠธ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ž‘์—…
LOGIN

์›น์‚ฌ์ดํŠธ์— ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค.

REGISTRATION ์›น์‚ฌ์ดํŠธ ๋“ฑ๋ก.
SECURITY_QUESTION_CHANGE ๋ณด์•ˆ ์งˆ๋ฌธ ๋ณ€๊ฒฝ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
PASSWORD_RESET ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
PHONE_NUMBER_UPDATE ์ „ํ™”๋ฒˆํ˜ธ ์—…๋ฐ์ดํŠธ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
EMAIL_UPDATE ์ด๋ฉ”์ผ ์ฃผ์†Œ ์—…๋ฐ์ดํŠธ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
ACCOUNT_UPDATE ์—ฐ๋ฝ์ฒ˜ ์„ธ๋ถ€์ •๋ณด์™€ ๊ฐ™์€ ๊ณ„์ • ๊ด€๋ จ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
TRIGGER_MFA MFA ์ฑŒ๋ฆฐ์ง€๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.
REDEEM_CODE ์ฝ”๋“œ ์‚ฌ์šฉ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
LIST_PAYMENT_METHODS ๊ฒฐ์ œ ์ˆ˜๋‹จ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ๋Š” ์ „ํ™”๋ฒˆํ˜ธ ์—…๋ฐ์ดํŠธ ์‹œ grecaptcha.enterprise.execute()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    <script>
    function onClick(e) {
      e.preventDefault();
      grecaptcha.enterprise.ready(async () => {
        const token = await grecaptcha.enterprise.execute('KEY_ID', {action: 'PHONE_NUMBER_UPDATE'});
      });
    }
    </script>
    

์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ ํ‰๊ฐ€

์‚ฌ์šฉ์ž ์ž‘์—…์—์„œ grecaptcha.enterprise.execute()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ† ํฐ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์„ฑ๊ณต ๋ฐ ์‹คํŒจํ•œ ๋กœ๊ทธ์ธ, ๋“ฑ๋ก, ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ์ž‘์—…๊ณผ ๊ฐ™์€ ์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด grecaptcha.enterprise.execute() ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ํ‰๊ฐ€๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ‰๊ฐ€๋Š” ์ž ์žฌ์ ์ธ ํ—ˆ์œ„ ํ–‰์œ„๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฒฐ์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์œ„ํ—˜ ํŒ์ •์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•œ ์ž‘์—… ์ค‘ ์ผ๋ถ€๋Š” ์˜์‹ฌ์Šค๋Ÿฌ์šด ์š”์ฒญ ์ฐจ๋‹จ, ์œ„ํ—˜ํ•œ ๋กœ๊ทธ์ธ ์‹œ๋„, ๊ด€์‹ฌ ๊ณ„์ • ์กฐ์‚ฌ์ž…๋‹ˆ๋‹ค.

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋กœ๊ทธ์ธ ์š”์ฒญ, ๋กœ๊ทธ์ธํ•œ ์š”์ฒญ, ๊ฐ€์ž… ์š”์ฒญ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ํ™œ๋™์„ ํŠน์ • ๊ณ„์ •์—์„œ ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ์ž ํ™œ๋™ ํŒจํ„ด์„ ์ดํ•ดํ•˜๊ณ  ๊ฐ ๊ณ„์ •์˜ ํ™œ๋™ ๋ชจ๋ธ์„ ๋นŒ๋“œํ•˜์—ฌ ๋น„์ •์ƒ ํŠธ๋ž˜ํ”ฝ๊ณผ ์•…์˜์ ์ธ ํŠธ๋ž˜ํ”ฝ์„ ๋”์šฑ ํšจ๊ณผ์ ์œผ๋กœ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ž์ฃผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž accountId๋ฅผ ์„ ํƒํ•˜๊ณ  projects.assessments.create ๋ฉ”์„œ๋“œ์˜ ํ‰๊ฐ€์— ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž๋Š” ๋™์ผํ•œ ์‚ฌ์šฉ์ž์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ด๋ฒคํŠธ์—์„œ ๊ฐ™์€ ๊ฐ’์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณ„์ • ์‹๋ณ„์ž๋กœ ๋‹ค์Œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์‹๋ณ„์ž

๋ชจ๋“  ๊ณ„์ •์„ ์•ˆ์ •์ ์ธ ์‚ฌ์šฉ์ž ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ์ „ํ™”๋ฒˆํ˜ธ์™€ ๊ณ ์œ ํ•˜๊ฒŒ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ accountId๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ต์ฐจ ์‚ฌ์ดํŠธ ์‹๋ณ„์ž(์‚ฌ์ดํŠธ ๊ฐ„์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹๋ณ„์ž)๋ฅผ ์ œ๊ณตํ•˜๋ฉด reCAPTCHA๊ฐ€ ์ด ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•…์šฉ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์‹ ๊ณ ํ•˜๊ณ  ์ด๋Ÿฌํ•œ ์‹๋ณ„์ž์™€ ๊ด€๋ จ๋œ ๊ต์ฐจ ์‚ฌ์ดํŠธ ์•…์šฉ ํŒจํ„ด์— ๋Œ€ํ•œ ์ง€์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ต์ฐจ ์‚ฌ์ดํŠธ ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž ๊ณ„์ • ๋ณดํ˜ธ๋ฅผ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜๋Š” ๊ฐ ๊ณ„์ •๊ณผ ๊ณ ์œ ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋œ ๋‚ด๋ถ€ ์‚ฌ์šฉ์ž ID๊ฐ€ ์žˆ์œผ๋ฉด ์ด๋ฅผ accountId๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด์‹ฑ ๋˜๋Š” ์•”ํ˜ธํ™”๋จ

๊ฐ ๊ณ„์ •์— ๊ณ ์œ ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋œ ๋‚ด๋ถ€ ์‚ฌ์šฉ์ž ID๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์•ˆ์ •์ ์ธ ์‹๋ณ„์ž๋ฅผ ์‚ฌ์ดํŠธ๋ณ„ ๋ถˆํ™•์‹คํ•œ ๊ณ„์ • ์‹๋ณ„์ž๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์‹๋ณ„์ž๋Š” reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ์ž ํ™œ๋™ ํŒจํ„ด์„ ์ดํ•ดํ•˜๊ณ  ๋น„์ •์ƒ์ ์ธ ๋™์ž‘์„ ๊ฐ์ง€ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ ๊ฐ„์— ๊ณต์œ ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

reCAPTCHA์— ์ „์†กํ•˜๊ธฐ ์ „์— ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์„ ํƒํ•˜๊ณ  ์•”ํ˜ธํ™” ๋˜๋Š” ํ•ด์‹ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆํ™•์‹คํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  • ์•”ํ˜ธํ™”(๊ถŒ์žฅ): ์•ˆ์ •์ ์ธ ์•”ํ˜ธ๋ฌธ์„ ์ƒ์„ฑํ•˜๋Š” ํ™•์ •์  ์•”ํ˜ธํ™” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์•”ํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์•ˆ๋‚ด๋Š” ํ™•์ •์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ํ•ด์‹ฑ ๋Œ€์‹  ๋Œ€์นญ์  ์•”ํ˜ธํ™”๋ฅผ ์„ ํƒํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž์™€ ํ•ด๋‹น ๋ถˆํ™•์‹คํ•œ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž ๊ฐ„์— ๋งคํ•‘์„ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. reCAPTCHA์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ถˆํ™•์‹คํ•œ ์‹๋ณ„์ž๋ฅผ ๋ณตํ˜ธํ™”ํ•˜์—ฌ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ํ•ด์‹ฑ: SHA256-HMAC ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ์ปค์Šคํ…€ ์†”ํŠธ๋กœ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ํ•ด์‹ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•ด์‹œ๋Š” ๋‹จ๋ฐฉํ–ฅ์ด๋ฏ€๋กœ, ์›๋ž˜ ๊ณ„์ •์œผ๋กœ ๋‹ค์‹œ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ํ•ด์‹œ๋œ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒ์„ฑ๋œ ํ•ด์‹œ์™€ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž ๊ฐ„์— ๋งคํ•‘์„ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ณ„์ • ๊ด€๋ จ ์š”์ฒญ์— ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์ผ๋ถ€ ํŠน์ • ์š”์ฒญ์— ๋ถˆ์•ˆ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. accountId ์™ธ์— ์ œ๊ณต๋˜๋Š” ์ปจํ…์ŠคํŠธ๋ณ„ ๊ณ„์ • ์‹๋ณ„์ž๋Š” reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ์ž ํ™œ๋™์„ ๋” ์ž˜ ์ดํ•ดํ•˜๊ณ  ๊ณ„์ • ํƒˆ์ทจ ์‹œ๋„๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ณ„์ •์„ ์•ˆ์ „ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•˜๋ฉด reCAPTCHA๊ฐ€ ์ด ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•…์šฉ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์‹ ๊ณ ํ•˜๊ณ  ์ด๋Ÿฌํ•œ ์‹๋ณ„์ž์™€ ๊ด€๋ จ๋œ ๊ต์ฐจ ์‚ฌ์ดํŠธ ์•…์šฉ ํŒจํ„ด์— ๋Œ€ํ•œ ์ง€์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ต์ฐจ ์‚ฌ์ดํŠธ ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž ๊ณ„์ • ๋ณดํ˜ธ๋ฅผ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ์œ„ํ•ด ๋กœ๊ทธ์ธ ํ•ธ๋“ค๋กœ ์‚ฌ์šฉ๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ์ „ํ™”๋ฒˆํ˜ธ

  • ๋‹ค์ค‘ ์ธ์ฆ(MFA) ์š”์ฒญ์„ ์œ„ํ•ด ์ธ์ฆ๋œ ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ์ „ํ™”๋ฒˆํ˜ธ

  • ๊ณ„์ • ์—…๋ฐ์ดํŠธ๋ฅผ ์š”์ฒญํ•˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋˜๋Š” ์ „ํ™”๋ฒˆํ˜ธ(๊ธฐ๋ณธ ๋˜๋Š” ๋ณด์กฐ)

  • ๋“ฑ๋ก ์š”์ฒญ ์ค‘์— ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ์ด๋ฉ”์ผ ์ฃผ์†Œ ๋ฐ ์ „ํ™”๋ฒˆํ˜ธ

์„ ํƒํ•œ ์•ˆ์ •์ ์ธ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ๋ชจ๋“  ๊ณ„์ • ๊ด€๋ จ ์š”์ฒญ projects.assessments.create ๋ฉ”์„œ๋“œ์˜ accountId ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๊ฒฝ์šฐ ํ‰๊ฐ€์—์„œ userIds ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ จ ์š”์ฒญ์— ์ถ”๊ฐ€ ๊ณ„์ • ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  • PROJECT_ID: Google Cloud ํ”„๋กœ์ ํŠธ ID
  • TOKEN: grecaptcha.enterprise.execute() ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜ ํ† ํฐ
  • KEY_ID: ์‚ฌ์ดํŠธ์™€ ์—ฐ๊ฒฐ๋œ reCAPTCHA ํ‚ค
  • ACCOUNT_ID: ์›น์‚ฌ์ดํŠธ์˜ ์‚ฌ์šฉ์ž ๊ณ„์ •์— ๋Œ€ํ•ด ํ•ด๋‹น ์‚ฌ์šฉ์ž ๊ณ„์ •๊ณผ ๊ณ ์œ ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋œ ์‹๋ณ„์ž
  • EMAIL_ADDRESS: (์„ ํƒ์‚ฌํ•ญ) ์ด ์š”์ฒญ๊ณผ ์—ฐ๊ฒฐ๋œ ์ด๋ฉ”์ผ ์ฃผ์†Œ(์žˆ๋Š” ๊ฒฝ์šฐ)
  • PHONE_NUMBER: (์„ ํƒ์‚ฌํ•ญ) ์ด ์š”์ฒญ๊ณผ ์—ฐ๊ฒฐ๋œ ์ „ํ™”๋ฒˆํ˜ธ(์žˆ๋Š” ๊ฒฝ์šฐ)
  • USERNAME: (์„ ํƒ์‚ฌํ•ญ) ์ด ์š”์ฒญ๊ณผ ์—ฐ๊ฒฐ๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„(์žˆ๋Š” ๊ฒฝ์šฐ)

HTTP ๋ฉ”์„œ๋“œ ๋ฐ URL:

POST https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments

JSON ์š”์ฒญ ๋ณธ๋ฌธ:

{
  "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "userInfo": {
      "accountId": "ACCOUNT_ID",
      "userIds": [
        {
          "email": "EMAIL_ADDRESS"
        },
        {
          "phoneNumber": "PHONE_NUMBER"
        },
        {
          "username": "USERNAME"
        }
      ]
    }
  }
}

์š”์ฒญ์„ ๋ณด๋‚ด๋ ค๋ฉด ๋‹ค์Œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

curl

์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments"

PowerShell

์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments" | Select-Object -Expand Content

๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ JSON ์‘๋‹ต์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

{
  "tokenProperties": {
    "valid": true,
    "hostname": "www.google.com",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY",
    "userInfo": {
      "accountId": "ACCOUNT_ID"
    }
  },
  "name": "projects/PROJECT_NUMBER/assessments/b6ac310000000000",
  "accountDefenderAssessment": {
    "labels": ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

์ฝ”๋“œ ์ƒ˜ํ”Œ

Java

reCAPTCHA์— ์ธ์ฆํ•˜๋ ค๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์˜ ์ธ์ฆ ์„ค์ •์„ ์ฐธ์กฐํ•˜์„ธ์š”.


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AccountDefenderAssessment.AccountDefenderLabel;
import com.google.recaptchaenterprise.v1.Assessment;
import com.google.recaptchaenterprise.v1.CreateAssessmentRequest;
import com.google.recaptchaenterprise.v1.Event;
import com.google.recaptchaenterprise.v1.ProjectName;
import com.google.recaptchaenterprise.v1.RiskAnalysis.ClassificationReason;
import com.google.recaptchaenterprise.v1.TokenProperties;
import com.google.recaptchaenterprise.v1.UserId;
import com.google.recaptchaenterprise.v1.UserInfo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class AccountDefenderAssessment {

  public static void main(String[] args)
      throws IOException, NoSuchAlgorithmException, InvalidKeyException {
    // TODO(developer): Replace these variables before running the sample.
    // projectId: Google Cloud Project ID
    String projectId = "project-id";

    // recaptchaSiteKey: Site key obtained by registering a domain/app to use recaptcha
    // services.
    String recaptchaSiteKey = "recaptcha-site-key";

    // token: The token obtained from the client on passing the recaptchaSiteKey.
    // To get the token, integrate the recaptchaSiteKey with frontend. See,
    // https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#frontend_integration_score
    String token = "recaptcha-token";

    // recaptchaAction: The action name corresponding to the token.
    String recaptchaAction = "recaptcha-action";

    // Unique ID of the user, such as email, customer ID, etc.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    // User phone number
    String phoneNumber = "555-987-XXXX";

    // User email address
    String emailAddress = "john.doe@example.com";

    accountDefenderAssessment(projectId, recaptchaSiteKey, token, recaptchaAction, accountId, phoneNumber, emailAddress);
  }

  /**
   * This assessment detects account takeovers. See,
   * https://cloud.google.com/recaptcha-enterprise/docs/account-takeovers The input is the hashed
   * account id. Result tells if the action represents an account takeover. You can optionally
   * trigger a Multi-Factor Authentication based on the result.
   */
  public static void accountDefenderAssessment(
      String projectId,
      String recaptchaSiteKey,
      String token,
      String recaptchaAction,
      String accountId,
      String phoneNumber,
      String emailAddress)
      throws IOException {
    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

      // Set the properties of the event to be tracked.
      Event.Builder eventBuilder =
          Event.newBuilder()
              .setSiteKey(recaptchaSiteKey)
              .setToken(token);

      // Set the account id, email address and phone number (of the user).
      eventBuilder.setUserInfo(
        UserInfo.newBuilder()
          .setAccountId(accountId)
          .addUserIds(UserId.newBuilder().setEmail(emailAddress))
          .addUserIds(UserId.newBuilder().setPhoneNumber(phoneNumber)));

      Event event = eventBuilder.build();

      // Build the assessment request.
      CreateAssessmentRequest createAssessmentRequest =
          CreateAssessmentRequest.newBuilder()
              .setParent(ProjectName.of(projectId).toString())
              .setAssessment(Assessment.newBuilder().setEvent(event).build())
              .build();

      Assessment response = client.createAssessment(createAssessmentRequest);

      // Check integrity of the response token.
      if (!checkTokenIntegrity(response.getTokenProperties(), recaptchaAction)) {
        return;
      }

      // Get the reason(s) and the reCAPTCHA risk score.
      // For more information on interpreting the assessment,
      // see: https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
      for (ClassificationReason reason : response.getRiskAnalysis().getReasonsList()) {
        System.out.println(reason);
      }
      float recaptchaScore = response.getRiskAnalysis().getScore();
      System.out.println("The reCAPTCHA score is: " + recaptchaScore);
      String assessmentName = response.getName();
      System.out.println(
          "Assessment name: " + assessmentName.substring(assessmentName.lastIndexOf("/") + 1));

      // Get the Account Defender result.
      com.google.recaptchaenterprise.v1.AccountDefenderAssessment accountDefenderAssessment =
          response.getAccountDefenderAssessment();
      System.out.println(accountDefenderAssessment);

      // Get Account Defender label.
      List<AccountDefenderLabel> defenderResult =
          response.getAccountDefenderAssessment().getLabelsList();
      // Based on the result, can you choose next steps.
      // If the 'defenderResult' field is empty, it indicates that Account Defender did not have
      // anything to add to the score.
      // Few result labels: ACCOUNT_DEFENDER_LABEL_UNSPECIFIED, PROFILE_MATCH,
      // SUSPICIOUS_LOGIN_ACTIVITY, SUSPICIOUS_ACCOUNT_CREATION, RELATED_ACCOUNTS_NUMBER_HIGH.
      // For more information on interpreting the assessment, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/account-defender#interpret-assessment-details
      System.out.println("Account Defender Assessment Result: " + defenderResult);
    }
  }

  private static boolean checkTokenIntegrity(
      TokenProperties tokenProperties, String recaptchaAction) {
    // Check if the token is valid.
    if (!tokenProperties.getValid()) {
      System.out.println(
          "The Account Defender Assessment call failed because the token was: "
              + tokenProperties.getInvalidReason().name());
      return false;
    }

    // Check if the expected action was executed.
    if (!tokenProperties.getAction().equals(recaptchaAction)) {
      System.out.printf(
          "The action attribute in the reCAPTCHA tag '%s' does not match "
              + "the action '%s' you are expecting to score",
          tokenProperties.getAction(), recaptchaAction);
      return false;
    }
    return true;
  }
}

์ค‘์š”ํ•œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ์˜ ์œ„ํ—˜ ํŒ์ • ํ•ด์„

๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ ์„ค์ •๋œ ํ‰๊ฐ€๋ฅผ ๋งŒ๋“ค๋ฉด ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ํ‰๊ฐ€ ์‘๋‹ต์˜ ์ผ๋ถ€๋กœ accountDefenderAssessment๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. accountDefenderAssessment ๊ฐ’์€ ์‚ฌ์šฉ์ž ํ™œ๋™์ด ํ•ฉ๋ฒ•์ ์ธ์ง€ ๋˜๋Š” ์‚ฌ๊ธฐ์ธ์ง€ ํ‰๊ฐ€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ํ‰๊ฐ€ ID๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ๋Š” ์ƒ˜ํ”Œ JSON ์‘๋‹ต์ž…๋‹ˆ๋‹ค.

{
  "tokenProperties": {
    "valid": true,
    "hostname": "www.google.com",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "expectedAction": "USER_ACTION"
  },
  "name": "projects/PROJECT_ID/assessments/b6ac310000000000X",
  "accountDefenderAssessment": {
    labels: ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

accountDefenderAssessment ํ•„๋“œ์—๋Š” ๋‹ค์Œ ๊ฐ’์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ’ ์„ค๋ช…
SUSPICIOUS_LOGIN_ACTIVITY ํ•ด๋‹น ์š”์ฒญ์ด ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด ์ฑ„์šฐ๊ธฐ ๋˜๋Š” ๊ณ„์ • ํƒˆ์ทจ์˜ ์œ„ํ—˜์ด ๋†’์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
SUSPICIOUS_ACCOUNT_CREATION ํ•ด๋‹น ์š”์ฒญ์ด ์•…์šฉ๋˜๋Š” ๊ณ„์ •์„ ๋งŒ๋“ค ์œ„ํ—˜์ด ๋†’์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
PROFILE_MATCH

์‚ฌ์šฉ์ž ์†์„ฑ์ด ์ด์ „์— ์ด ํŠน์ • ์‚ฌ์šฉ์ž์— ํ‘œ์‹œ๋œ ์†์„ฑ๊ณผ ์ผ์น˜ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ์ด ์‚ฌ์šฉ์ž๊ฐ€ ์ด์ „์— ์›น์‚ฌ์ดํŠธ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•œ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๊ธฐ์— ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

PROFILE_MATCH๋Š” ๋‹ค์Œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋งŒ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋‹จ๊ณ„(MFA) ๋˜๋Š” 2๋‹จ๊ณ„ ์ธ์ฆ(2FA)์„ ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ MFA ๋˜๋Š” 2FA ์ฑŒ๋ฆฐ์ง€๋ฅผ ํ†ต๊ณผํ•œ ํ›„ reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ์šฐ
  • ์‚ฌ์šฉ์ž๊ฐ€ ํ‰๊ฐ€๋ฅผ LEGITIMATE ๋˜๋Š” PASSED_TWO_FACTOR๋กœ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๋ฉฐ reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๊ฐ€ ํ•ด๋‹น ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ์šฐ
RELATED_ACCOUNTS_NUMBER_HIGH ์š”์ฒญ์— ๊ด€๋ จ ๊ณ„์ •์ด ๋งŽ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ณ„์ •์ด ๋ฐ˜๋“œ์‹œ ์ž˜๋ชป๋œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ถ”๊ฐ€ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์ดํŠธ๋ณ„ ๋ชจ๋ธ ์กฐ์ •

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์— ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์‚ฌ์ดํŠธ๋ณ„ ๊ฐ์ง€ ๋ชจ๋ธ์„ ๊ฐœ์„ ํ•˜๋ ค๋ฉด ํ‰๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด์„œ ํ‰๊ฐ€ํ•œ ์ด๋ฒคํŠธ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ‰๊ฐ€ ID๋ฅผ ์‚ฌ์šฉํ•ด์„œ projects.assessments.annotate ๋ฉ”์„œ๋“œ์— ์š”์ฒญ์„ ์ „์†กํ•˜์—ฌ ํ‰๊ฐ€์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ ๋ณธ๋ฌธ์— ํ‰๊ฐ€์— ์„ค๋ช…๋œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ผ๋ฒจ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

ํ‰๊ฐ€์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ ์š”์ฒญ JSON ๋ณธ๋ฌธ์— ์ถ”๊ฐ€ํ•  ์ •๋ณด ๋ฐ ๋ผ๋ฒจ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    ๋‹ค์Œ ํ‘œ์—๋Š” ์ด๋ฒคํŠธ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ๋ฒจ๊ณผ ๊ฐ’์ด ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋ผ๋ฒจ ์„ค๋ช… ์š”์ฒญ ์˜ˆ์‹œ
    reasons ํ•„์ˆ˜ ํ•ญ๋ชฉ. ํ‰๊ฐ€๋ฅผ ์ง€์›ํ•˜๋Š” ๋ผ๋ฒจ์ž…๋‹ˆ๋‹ค.

    ์‹ค์‹œ๊ฐ„ ๊ฐ์ง€์— ์˜ํ–ฅ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ๋ฐœ์ƒ ํ›„ ๋ช‡ ์ดˆ ๋˜๋Š” ๋ช‡ ๋ถ„ ์ด๋‚ด์— reasons ๋ผ๋ฒจ์— ์‹ค์‹œ๊ฐ„ ์ด๋ฒคํŠธ ์„ธ๋ถ€์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ๊ฐ€๋Šฅํ•œ ๊ฐ’ ๋ชฉ๋ก์€ ์ด์œ  ๊ฐ’์„ ์ฐธ์กฐํ•˜์„ธ์š”.

    ์˜ˆ์‹œ: ๊ณ„์ • ํƒˆ์ทจ๋ฅผ ๊ฐ์ง€ํ•˜๋ ค๋ฉด ์ž…๋ ฅํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ CORRECT_PASSWORD ๋˜๋Š” INCORRECT_PASSWORD ๊ฐ’์— ์˜ฌ๋ฐ”๋ฅธ์ง€ ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ž์ฒด MFA๋ฅผ ๋ฐฐํฌํ•œ ๊ฒฝ์šฐ INITIATED_TWO_FACTOR, PASSED_TWO_FACTOR, FAILED_TWO_FACTOR ๊ฐ’์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

          {
          "reasons": ["INCORRECT_PASSWORD"]
          }
        
    annotation ์„ ํƒ์‚ฌํ•ญ. ํ‰๊ฐ€ ์ ๋ฒ•์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ผ๋ฒจ์ž…๋‹ˆ๋‹ค.

    annotation ๋ผ๋ฒจ์—์„œ ์œ„ํ—˜ ํ‰๊ฐ€๋ฅผ ๊ฒ€์ฆํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋กœ๊ทธ์ธ ๋ฐ ๋“ฑ๋ก ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‚ฌ์‹ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ LEGITIMATE ๋˜๋Š” FRAUDULENT์ž…๋‹ˆ๋‹ค.

    ์ด ์ •๋ณด๋Š” ์–ธ์ œ๋“ ์ง€ ๋˜๋Š” ์ผ๊ด„ ์ž‘์—…์„ ํ†ตํ•ด ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์‹œ๊ฐ„ ๊ฐ์ง€์— ์˜ํ–ฅ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ํ›„ ๋ช‡ ์ดˆ ๋˜๋Š” ๋ช‡ ๋ถ„ ์ด๋‚ด์— ์ด ์ •๋ณด๋ฅผ ์ „์†กํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

          {
           "annotation": "LEGITIMATE"
          }
    
      
    accountId

    ์„ ํƒ์‚ฌํ•ญ. ๊ณ„์ • ID๋ฅผ ์ด๋ฒคํŠธ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ผ๋ฒจ์ž…๋‹ˆ๋‹ค.

    ๊ณ„์ • ID ์—†์ด ํ‰๊ฐ€๋ฅผ ์ƒ์„ฑํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•  ๋•Œ๋งˆ๋‹ค ์ด ๋ผ๋ฒจ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ์˜ ๊ณ„์ • ID๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

      {
       "accountId": "ACCOUNT_ID"
      }
  2. ์ ์ ˆํ•œ ๋ผ๋ฒจ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฃผ์„ ์š”์ฒญ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • ASSESSMENT_ID: projects.assessments.create ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ name ํ•„๋“œ ๊ฐ’์ž…๋‹ˆ๋‹ค.
    • ANNOTATION: (์„ ํƒ์‚ฌํ•ญ) ํ‰๊ฐ€๊ฐ€ ํƒ€๋‹นํ•œ์ง€ ๋˜๋Š” ํ—ˆ์œ„์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ผ๋ฒจ์ž…๋‹ˆ๋‹ค.
    • REASONS: ์„ ํƒ์‚ฌํ•ญ. ์ฃผ์„์„ ์ง€์›ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฐ’ ๋ชฉ๋ก์€ ์ด์œ  ๊ฐ’์„ ์ฐธ์กฐํ•˜์„ธ์š”.
    • ACCOUNT_ID: ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์›น์‚ฌ์ดํŠธ์˜ ์‚ฌ์šฉ์ž ๊ณ„์ •๊ณผ ๊ณ ์œ ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋œ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค.

    ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ฃผ์„ ๋ผ๋ฒจ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

    HTTP ๋ฉ”์„œ๋“œ ๋ฐ URL:

    POST https://recaptchaenterprise.googleapis.com/v1/ASSESSMENT_ID:annotate

    JSON ์š”์ฒญ ๋ณธ๋ฌธ:

    {
      "annotation": ANNOTATION,
      "reasons": REASONS,
      "accountId": ACCOUNT_ID
    }
    

    ์š”์ฒญ์„ ๋ณด๋‚ด๋ ค๋ฉด ๋‹ค์Œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

    curl

    ์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    curl -X POST \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d @request.json \
    "https://recaptchaenterprise.googleapis.com/v1/ASSESSMENT_ID:annotate"

    PowerShell

    ์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    $cred = gcloud auth print-access-token
    $headers = @{ "Authorization" = "Bearer $cred" }

    Invoke-WebRequest `
    -Method POST `
    -Headers $headers `
    -ContentType: "application/json; charset=utf-8" `
    -InFile request.json `
    -Uri "https://recaptchaenterprise.googleapis.com/v1/ASSESSMENT_ID:annotate" | Select-Object -Expand Content

    ์„ฑ๊ณต ์ƒํƒœ ์ฝ”๋“œ(2xx)์™€ ๋นˆ ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒ˜ํ”Œ

Java

reCAPTCHA์— ์ธ์ฆํ•˜๋ ค๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์˜ ์ธ์ฆ ์„ค์ •์„ ์ฐธ์กฐํ•˜์„ธ์š”.


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Annotation;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Reason;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentResponse;
import com.google.recaptchaenterprise.v1.AssessmentName;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class AnnotateAccountDefenderAssessment {

  public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
    // TODO(developer): Replace these variables before running the sample.
    // projectID: GCloud Project id.
    String projectID = "project-id";

    // assessmentId: Value of the 'name' field returned from the CreateAssessment call.
    String assessmentId = "account-defender-assessment-id";

    // accountId: Set the accountId corresponding to the assessment id.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    annotateAssessment(projectID, assessmentId, accountId);
  }

  /**
   * Pre-requisite: Create an assessment before annotating. Annotate an assessment to provide
   * feedback on the correctness of recaptcha prediction.
   */
  public static void annotateAssessment(
      String projectID, String assessmentId, String accountId) throws IOException {

    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {
      // Build the annotation request.
      // For more info on when/how to annotate, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/annotate-assessment#when_to_annotate
      AnnotateAssessmentRequest annotateAssessmentRequest =
          AnnotateAssessmentRequest.newBuilder()
              .setName(AssessmentName.of(projectID, assessmentId).toString())
              .setAnnotation(Annotation.LEGITIMATE)
              .addReasons(Reason.PASSED_TWO_FACTOR)
              .setAccountId(accountId)
              .build();

      // Empty response is sent back.
      AnnotateAssessmentResponse response = client.annotateAssessment(annotateAssessmentRequest);
      System.out.println("Annotated response sent successfully ! " + response);
    }
  }
}

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ ์‚ฌ์šฉ ์„ค์ •

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์˜ ์›นํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•œ ํ›„์— reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Google Cloud ์ฝ˜์†”์—์„œ reCAPTCHA ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    reCAPTCHA๋กœ ์ด๋™

  2. ํŽ˜์ด์ง€ ์ƒ๋‹จ์˜ ๋ฆฌ์†Œ์Šค ์„ ํƒ๊ธฐ์— ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์ด ํ‘œ์‹œ๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์ด ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์†Œ์Šค ์„ ํƒ๊ธฐ๋ฅผ ํด๋ฆญํ•œ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  3. ์„ค์ • ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  4. ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ ์ฐฝ์—์„œ ๊ตฌ์„ฑ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  5. ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ ๊ตฌ์„ฑ ๋Œ€ํ™”์ƒ์ž์—์„œ ์‚ฌ์šฉ ์„ค์ •์„ ํด๋ฆญํ•œ ํ›„ ์ €์žฅ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

reCAPTCHA ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ ์‚ฌ์šฉ ์„ค์ •์ด Google ์‹œ์Šคํ…œ์— ์ „ํŒŒ๋˜๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์„ค์ •์ด Google ์‹œ์Šคํ…œ์— ์ „ํŒŒ๋˜๋ฉด ํ‰๊ฐ€์˜ ์ผํ™˜์œผ๋กœ ๊ณ„์ • ๋ฐฉ์–ด ๋„๊ตฌ์™€ ๊ด€๋ จ๋œ ์‘๋‹ต์„ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„