Google’ın reCaptcha API’si web sitenizi / uygulamanızı kötü amaçlı trafiğe karşı korur. ReCaptcha’yı web sayfalarına entegre edilmiş görmüş olabilirsiniz.
Hizmetin kullanımı ücretsizdir ve eğer motor kullanıcı etkileşiminin insan yerine bir bot olduğundan şüphelenirse çözülmesi gereken bir Captcha’yı gösterecektir.
Sadece formları değil, captcha’yı uygulamanızdaki herhangi bir modüle entegre edebilirsiniz.
Nasıl çalışır?
ReCAPTCHA, uygulamanız, SafetyNet sunucusu ve sunucunuz arasında belirli ağ aramaları yapılarak doğrulanır .
- Öncelikle, uygulamanızı kaydederek SafetyNet anahtar çiftini edinmeniz gerekir. Site Anahtarı ve ScretKey’i alacaksınız .
- Site Key android uygulamasına entegre olacak ve halka açık olabilir. Sır sunucunuzda tutulmalı ve açıkta kalmamalıdır.
- ReCaptcha çağrıldığında, gerekirse kullanıcıya Captcha yarışmasını gösterecektir. Bu adımda captcha sunucusu ile iletişim kurar ve Site tuşunu kullanarak Kullanıcı Yanıt Simgesini döndürür .
- Kullanıcı Yanıt Simgesi alındığında, sunucuda Gizli anahtar kullanılarak doğrulanması gerekir .
- Mobil uygulamadan, Kullanıcı Yanıt Simgesi sunucunuza gönderilir. Sunucudan belirteç, Secret ile birlikte SafetyNet sunucusuna gönderilir. SafetyNet sunucusu simgeyi doğruladıktan sonra sunucunuzu başarı durumu ile bilgilendirir.
- Son olarak, sunucunuz mobil uygulamayı captcha durumu ile bildirir, yani başarılı veya başarısız olur.
SafetyNet Site Anahtarının ve ScretKey’in Alınması
Site Anahtarınızı ve Sırrınızı edinmek için aşağıdaki adımları izleyin.
- reCaptcha Kayıt sayfasını açın ve uygulamanızı kaydedin.
- Anahtarı tanımlamak için etiketi girin . Uygulama adınızı veya ekran adınızı verebilirsiniz.
- ReCaptcha türünü seçin. ReCaptcha Android’i seçmeyi tercih ederim.
- Uygulama paketinizin adını girin . Aynı anahtar için birden fazla uygulama paketi adı girebilirsiniz.
- Hizmet Şartlarını kabul edin ve Kayıt Ol düğmesine tıklayın. Kaydolduktan sonra, örnek kodla birlikte ekranda gösterilen Site Anahtarını ve ScretKey’i fark edebilirsiniz .
Yeni proje oluşturun.
Android Studio’da Dosya menüsünden yeni proje oluştur seçeneğine tıklayın. Ekrana gelen şablonlardan Temel Etkinlik ekranını seçin ve reCaptcha panosunda kaydettiğiniz paket adını kullanın.
Build grandle dosyasına SafetyNet dosyalarını projenize eklemek için implement edelim. Aynı zamanda sunucu tarafındaki captcha belirtecini doğrulamak için sunucumuza HTTP çağrısı gönderebilmek için Volley kütüphanesini implement edicez ve Arayüz ile Java kodları arasındaki bağlantıları hızlı bir şekilde yapabilmek için ButterKnife projesini implement ediyorum.
build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
// SafetyNet reCAPTCHA
implementation 'com.google.android.gms:play-services-safetynet:11.8.0'
// ButterKnife
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
// Volley
implementation 'com.android.volley:volley:1.1.0'
}
Bu makale hazırlanırken implement ettiğimiz kütüphanelerin sürümleri yenilenmiş olabilir. Lütfen internetten araştırarak yeni sürümleri kontrol edin. Yada File menüsünde Project Structure modülünde arama yaparak güncel kütüphaneleri bulabilirsiniz.
Ana aktivity layout dosyasını açın ve aşağıdaki kodları ekleyin. Renkler ve yazıları değiştirebilirsiniz.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="niximera.recaptcha.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/activity_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="info.androidhive.recaptcha.MainActivity"
tools:showIn="@layout/activity_main">
<LinearLayout
android:id="@+id/layout_feedback_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/title_form"
android:textColor="#666666"
android:textSize="20dp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/desc_form" />
<EditText
android:id="@+id/input_feedback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin"
android:gravity="top"
android:hint="@string/hint_feedback"
android:lines="5" />
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin"
style="@style/Widget.AppCompat.Button.Colored"
android:text="@string/btn_send"
android:textColor="@android:color/white" />
</LinearLayout>
<TextView
android:id="@+id/message_feedback_done"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:gravity="center"
android:padding="@dimen/activity_margin"
android:text="@string/message_feedback_done"
android:textSize="22dp"
android:visibility="gone" />
</LinearLayout>
MyApplication.java adlı yeni bir sınıf oluşturun ve sınıfı Application’dan genişletin. Bu sınıfta Volley örnekleri oluşturulur.
MyApplication.java
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
/**
* Created by ravi on 13/03/18.
*/
public class MyApplication extends Application {
public static final String TAG = MyApplication.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Manifest dosyasına internet iznini alabileceğiniz bir kod bloğu eklemeniz gerekmektedir.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.androidhive.recaptcha">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MyApplication">
</application>
</manifest>
Sonunda MainActivity.java’yı açın ve aşağıdaki değişiklikleri yapın.
- SAFETY_NET_API_SITE_KEY değerini api anahtarınızla değiştirin.
- URL_VERIFY_ON_SERVER sizin sunucu adresiniz olmalı.
- http://api.niximera/google-recaptcha-verfication.php sizin api adresiniz olmalı.
- validateCaptcha () , Captcha iletişim kutusunu gösterir ve doğrulama için sunucunuza gönderilmesi gereken Kullanıcı Yanıt Simgesini getirir .
- verifyTokenOnServer () yöntemi, alınan Kullanıcı Yanıt Simgesini Sırrı kullanarak doğrulamak için sunucuya gönderir. Sunucu, POST isteğini http://www.google.com/recaptcha/api/siteverify adresine gönderir ve belirteci doğrular.
- Belirteç sunucuda doğrulandıktan sonra, sunucunuz başarı durumuna sahip bir JSON’a yanıt verir. Başarı durumuna bağlı olarak daha fazla işlem yapmanız gerekir. Bu durumda, geribildirim gönderilmelidir.
MainActivity.java
package info.androidhive.recaptcha;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String SAFETY_NET_API_SITE_KEY = "6Lf8z0sUAAAAAP80KqD1U-3e7M_JlOrgWSms5XDd";
private static final String URL_VERIFY_ON_SERVER = "http://api.androidhive.info/google-recaptcha-verfication.php";
@BindView(R.id.input_feedback)
EditText inputFeedback;
@BindView(R.id.layout_feedback_form)
LinearLayout layoutFeedbackForm;
@BindView(R.id.message_feedback_done)
TextView messageFeedbackDone;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(getString(R.string.feedback));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Toast.makeText(getApplicationContext(), "Always check Android Studio `LogCat` for errors!", Toast.LENGTH_LONG).show();
}
@OnClick(R.id.btn_send)
public void validateCaptcha() {
String feedback = inputFeedback.getText().toString().trim();
// checking for empty feedback message
if (TextUtils.isEmpty(feedback)) {
Toast.makeText(getApplicationContext(), "Enter feedback!", Toast.LENGTH_LONG).show();
return;
}
SafetyNet.getClient(this).verifyWithRecaptcha(SAFETY_NET_API_SITE_KEY)
.addOnSuccessListener(this, new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
@Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
Log.d(TAG, "onSuccess");
if (!response.getTokenResult().isEmpty()) {
verifyTokenOnServer(response.getTokenResult());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Log.d(TAG, "Error message: " +
CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));
} else {
Log.d(TAG, "Unknown type of error: " + e.getMessage());
}
}
});
}
public void verifyTokenOnServer(final String token) {
Log.d(TAG, "Captcha Token" + token);
StringRequest strReq = new StringRequest(Request.Method.POST,
URL_VERIFY_ON_SERVER, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
boolean success = jsonObject.getBoolean("success");
String message = jsonObject.getString("message");
if (success) {
layoutFeedbackForm.setVisibility(View.GONE);
messageFeedbackDone.setVisibility(View.VISIBLE);
} else {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Json Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("recaptcha-response", token);
return params;
}
};
MyApplication.getInstance().addToRequestQueue(strReq);
}
}
Uygulamanın sunucu kısmı.
PHP kullanarak sunucunuzda yayımlama yapabileceğiniz kod bloğu aşağıdadır.
recaptcha-verfication.php
<?php
$ch = curl_init();
// TODO - Define your SafetyNet Secret in the below line
$secretKey = 'Place your SafetyNet Secret here';
$captcha = isset($_POST['recaptcha-response']) && !empty($_POST['recaptcha-response']) ? $_POST['recaptcha-response']: '';
curl_setopt_array($ch, [
CURLOPT_URL => 'http://www.google.com/recaptcha/api/siteverify',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'secret' => $secretKey,
'response' => $captcha,
'remoteip' => $_SERVER['REMOTE_ADDR']
],
CURLOPT_RETURNTRANSFER => true
]);
$output = curl_exec($ch);
curl_close($ch);
$json = json_decode($output);
$res = array();
if($json->success){
$res['success'] = true;
$res['message'] = 'Captcha verified successfully!';
}else{
$res['success'] = false;
$res['message'] = 'Failed to verify captcha!';
}
echo json_encode($res);
?>
ASP .net kullanarak sunucunuzda yayımlama yapabileceğiniz kod bloğu aşağıdadır.
<%@ Page Language="c#" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Configuration" %>
<%@ Import Namespace="System.Collections.Specialized" %>
<%@ Import Namespace="Newtonsoft.Json" %>
<%@ Import Namespace="System.Net.Http" %>
<script language="c#" runat="server">
public void Page_Load(object sender, EventArgs e)
{
var secretKey = "Place your SafetyNet Secret here";
using (var httpclient = new HttpClient())
{
var result = httpclient
.PostAsync("http://www.google.com/recaptcha/api/siteverify",
new StringContent(
JsonConvert.SerializeObject(new
{
'secret' = secretKey,
'response' = HttpContext.Current.Request.Form["captcha"],
'remoteip' = GetIpValue()
}),
System.Text.Encoding.UTF8,
"application/json"))
.Result
.Content
.ReadAsStringAsync()
.Result;
var resultObject = JsonConvert.DeserializeObject<ResponseClass>(result);
if (resultObject.success)
{
//success
HttpContext.Current.Response.Redirect("success.aspx");
}
else
{
HttpContext.Current.Response.Redirect("error.aspx");
//fail
}
}
}
class ResponseClass
{
public bool success { get; set; }
public string message { get; set; }
}
private void GetIpValue()
{
var ipAdd = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ipAdd))
{
ipAdd = Request.ServerVariables["REMOTE_ADDR"];
}
return ipAdd;
}
</script>
GIPHY App Key not set. Please check settings