آموزش ساخت reCAPTCHA با HTTPoison در الکسیر phoenix


#1

درود خدمت دوستان . امروز برای پیاده سازی فرم به سمت پیاده سازی reCAPTCHA رفتم اولش تصمیم گرفتم یک کتابخانه نصب کنم که دیدم خیلی ارور داره بعد تو پیوستگی های پلاگین دیدم که از HTTPoison استفاده می کنه به همین ترتیب یک کد ساده بدون کتابخانه آماده کردم ام. به شرح زیر

اول به لینک زیر برید
https://www.google.com/recaptcha/admin

بعد از وارد شدن اطلاعات دامنه رو بدید و دو کلید خصوصی و عمومی را دریافت کنید

در مرحله بعدی کد زیر را وارد قالب خودتان بکنید

<script src='https://www.google.com/recaptcha/api.js'></script>

در توضیحات گوگل اومده که:

Paste this snippet before the closing </head> tag on your HTML template:

حالا کد زیر رو در نمونه فرم خودتان قرار بدهید

<div class="g-recaptcha" data-sitekey="Site key"></div>

جایی که نوشته Site key همون کلید عمومی شما هست که در سایت گوگل بهتون داده است

نکته: نمایش و عدم نمایش چک کننده گوگل بر اساس داکیومنتش به چندین دسته تقسیم می شه که می تونید در لینک زیر بخونید(در منبع همین پست قرار دادم)

نمونه کدی که در قالب قرار دادم(فرم)

<div class="col-12 login-form rtl">
  <%= form_for @conn, user_path(@conn, :login_register_sender), fn f -> %>
    <div class="form-group">
      <label for="email">ایمیل</label>
      <%= email_input f, :email, class: "form-control", id: "login-email", autocomplete: "email", aria_describedby: "emailHelp", required: "" %>
      <small id="emailHelp" class="form-text text-muted">ایمیل شما با هیچ فرد و گروهی به اشتراک گذاشته نخواهد شد.</small>
    </div>

    <div class="form-group">
      <label for="password">پسورد</label>
      <%= password_input f, :password, class: "form-control", id: "passinput", autocomplete: "password", required: "" %>
    </div>

    <div class="recap">
      <div class="g-recaptcha" data-sitekey="6LfuiG8UAAAAAKo_a8krLO037O9imNIOT3fWLc6G"></div>
    </div>
    
    <%= submit "ارسال", class: "btn btn-primary" %>
  <% end %>
</div>

حالا زمان این هست که ریسپانسی که به واسطه کد مذکور با کلید عمومی شما درست می شه رو با کلید خصوصی خودتون به گوگل بفرستید با یک درخواست post توجه کنید این درخواست نباید json باشه

به عنوان مثال من اینجوری بررسی کردمش

def login_register_sender(conn, %{"name" => _name, "lastname" => _lastname, "email" => _email, "password" => _password} = info_of_register) do
    ip_os = TrangellHtmlSite.ip_os(conn)
    info_map = User.register_mapper(info_of_register)
    with {:ok, %HTTPoison.Response{status_code: 200, body: body_of_token}} <- TrangellHtmlSite.User.google_recap(info_of_register["g-recaptcha-response"]),
    %{"challenge_ts" => _time, "hostname" => _host, "success" => true} <- Jason.decode!(body_of_token),
    {:ok, %HTTPoison.Response{status_code: 200, body: _user_info}} <- User.register_sender(info_map, ip_os.ip, ip_os.os) do

اگر توجه کنید همراه params یا ورودی هایی که به تابع شما ارسال می شه به صورت زیر می تونید دریافتش کنید

info_of_register["g-recaptcha-response"]

و حالا کافیه اون رو به گوگل بفرستید . چیزایی که گوگل در خواست از شما می خواهد

کد های ارسالم

  def google_recap(response) do
    TrangellHtmlSite.google_post_recap("https://www.google.com/recaptcha/api/siteverify", %{"secret" => "SECRET_COD", "response" => response})
  end

و خود ارسال کننده درخواست

def google_post_recap(root_link, params) do
    body = "secret=#{params["secret"]}&response=#{params["response"]}"
    HTTPoison.post(
      "#{root_link}",
       body,
        [
          {"Content-Type", "application/x-www-form-urlencoded"},
          {"Accept", "text/html"}
        ],
       [timeout: 50_000, recv_timeout: 50_000]
    )
  end

توجه: اینجا کلید خصوصی به صورت هارد کد قرار گرفته شما باید اون رو در سیستم عاملتون ذخیره کنید و به وسیله الکسیر از متغییر سیستمیتون بخونید.

امید وارم مفید واقع بشه

توجه کلید خصوصی قرار گرفته در تصاویر کلید خصوصی تست بوده و حذف گردیده

منابع:

نمونه کد پست


#2

فقط یک مشکلی وجود داره اینکه در صفحه ای که کد چک کننده فعال می شه در داخل فرم یک اروری به شرح زیر می یاد

Uncaught TypeError: Cannot read property 'postMessageId' of null
    at onPostMessage (iframe.js:1000)
iframe.js:1000 Uncaught TypeError: Cannot read property 'postMessageId' of null
    at onPostMessage (iframe.js:1000)

اینو اگر دوستان نظری دارند چطور می شه رفعش کرد ممنون می شم


#4

js دقیقا کی لود میشه؟ اگر سایت در دسترس باشه بهتر میتونم چک کنم، اگرم نه که چک کردی ببینی شاید js زود لود میشه یا مشکل رندر وجود داره


#5

نه متاسفانه آنلاین نیست . یک بار تو تگ هد قرار دادم یک بار در آخر قالب قبل از بسته شدن body ولی باز هم همون ارور رو داره .

متاسفانه در زمینه js سواد بسیار کمی دارم . این مورد نمی دونم چطور بررسی کنم

ولی در کل

فایل مربوط در templates/layout/app.html.eex قرار دادم منظورم خط

<script src='https://www.google.com/recaptcha/api.js'></script>

و html اون مثلا در templates/user/login.html.eex می باشد
منظور خط

      <div class="g-recaptcha" data-sitekey="6LfuiG8UAAAAAKo_a8krLO037O9imNIOT3fWLc6G"></div>

کار می کنه ولی ارور های بالا رو هم می ده تازه دیدم که دوتا ارور دیگه هم داره تو صفحات دیگه هم می یاد

[Violation] Forced reflow while executing JavaScript took 82ms
[Violation] Forced reflow while executing JavaScript took 114ms

#6

alright!
بنظر v2 میاد, وقتی سورس رندر شده رو میبینی از ای پترن تبعیت میکنه؟

<html>
  <head>
    <title>reCAPTCHA demo: Simple page</title>
     <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="your_site_key"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

ref:
https://developers.google.com/recaptcha/docs/display


#7

در مرورگر!


#8

https://www.google.com/recaptcha/api2/demo


#9

نمونه به این صورته. قسمت فرم

<form accept-charset="UTF-8" action="/login-sender" method="post"><input name="_csrf_token" type="hidden" value="ekFMQV0ORy4oNTwvLn1GMH13MSExJgAAHp6t9IvhQbslf+wE9AgUCA=="><input name="_utf8" type="hidden" value="✓">    <div class="form-group">
      <label for="email">ایمیل</label>
<input aria-describedby="emailHelp" autocomplete="email" class="form-control" id="login-email" name="email" required="" type="email">      <small id="emailHelp" class="form-text text-muted">ایمیل شما با هیچ فرد و گروهی به اشتراک گذاشته نخواهد شد.</small>
    </div>

    <div class="form-group">
      <label for="password">پسورد</label>
<input autocomplete="password" class="form-control" id="passinput" name="password" required="" type="password">    </div>

    <div class="recap">
      <div class="g-recaptcha" data-sitekey="6LcSiW8UAAAAAPMAopdGZVFS22JyeWLUZGi9bvQu"><div style="width: 304px; height: 78px;"><div><iframe src="https://www.google.com/recaptcha/api2/anchor?ar=1&amp;k=6LcSiW8UAAAAAPMAopdGZVFS22JyeWLUZGi9bvQu&amp;co=aHR0cDovL2xvY2FsaG9zdDo5OTkx&amp;hl=en&amp;v=v1536180392857&amp;size=normal&amp;cb=1h8ynh7xo7p2" width="304" height="78" role="presentation" name="a-djuqr7eg6qiz" frameborder="0" scrolling="no" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox"></iframe></div><textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid #c1c1c1; margin: 10px 25px; padding: 0px; resize: none;  display: none; "></textarea></div></div>
    </div>

<button class="btn btn-primary" type="submit">ارسال</button>  </form>

قسمت head که لود می شه به این صورته

<script type="text/javascript" async="" src="https://www.gstatic.com/recaptcha/api2/v1536180392857/recaptcha__en.js"></script>

<script src="https://www.google.com/recaptcha/api.js"></script>

تبدیل به دوتا کد می شه


#10
<script type="text/javascript" async="" src="https://www.gstatic.com/recaptcha/api2/v1536180392857/recaptcha__en.js"></script>

نباید بعد از api باشه؟

<script src="https://www.google.com/recaptcha/api.js"></script>
<script type="text/javascript" async="" src="https://www.gstatic.com/recaptcha/api2/v1536180392857/recaptcha__en.js"></script>

#11

نه صبر کن, چرا دوتا api داری؟
الان دیدم


#12

خودش اینکارو می کنه من در کل فقط یک فایل رو در قالبم لود کردم بعد خودش تبدیل می کنه به این


#13

درست بنظر میاد, اشکال جای دیگست


#14

من جابه جاشم کردم ولی زیاد تاثیر نداشت اون پارامتر ها هم روش نبود اضافه کردم

<script src='https://www.google.com/recaptcha/api.js?hl=fa' async defer></script>

منظورم ایناست
async defer بازم مشکل حل نشد. حتی جالبه یک کتابخانه هم داشتم استفاده می کردم این ارور داشت


#15

doc رو چک کردم قبلی ok بود


#16

داشتم فکر میکردم شاید اون null property اصلا از recaptcha نباشه


#17

اینو تست کردی؟

   setTimeout(function() { $('div.g-recaptcha').hide(); }, 0);

#18

ولی وقتی html اش رو غیر فعال می کنم ارور می ره


#19

مستقیم بزارم توی فایل app.js هرجاش خواستم ؟ اگر آره همین الان زدم تاثیری نداشت


#20

دموی خود google توی هر مرورگری کلی خطاهای مختلف داره, بنظرم اگه کار میکنه سخت نگیر.
انگار کلا v2 یه سری مشکل داره


#21

شما که گفتید من خودم توی سایت خودمم هم تست کردم باز هم همین ارور دارم

https://trangell.com/fa/registration

مورد فعلی روی سایت خودم مخصوص خود جوملاست هم وجود داره شاید افزونه ای روی کرومم نصب هست که این مشکل رو داره. چون چنین فایلی آی فرم فکر نکنم توی سایتم داشته باشم اصلا