Browse Source

implemented captcha time validation on backend, added reload captcha option in javascript library

master
arnaucode 7 years ago
parent
commit
d2b874794a
4 changed files with 60 additions and 26 deletions
  1. +28
    -14
      README.md
  2. +22
    -8
      captcha.go
  3. +4
    -0
      web/goCaptcha.css
  4. +6
    -4
      web/goCaptcha.js

+ 28
- 14
README.md

@ -1,8 +1,8 @@
# goCaptcha # goCaptcha
captcha server, with own datasets, to train own machine learning AI captcha server, with own datasets, to train own machine learning AI
### How to use?
#### Frontend
## 1 - How to use?
### 1.1 - Frontend
Insert this lines in the html file: Insert this lines in the html file:
```html ```html
<link rel="stylesheet" href="goCaptcha.css"> <link rel="stylesheet" href="goCaptcha.css">
@ -19,7 +19,7 @@ It will place the goCaptcha box in the div:
![goCaptcha](https://raw.githubusercontent.com/arnaucode/goCaptcha/master/demo01.png "goCaptcha") ![goCaptcha](https://raw.githubusercontent.com/arnaucode/goCaptcha/master/demo01.png "goCaptcha")
#### Backend
### 1.2 - Backend
- Put dataset images in the folder 'imgs'. - Put dataset images in the folder 'imgs'.
- Run MongoDB. - Run MongoDB.
- Go to the folder /goCaptcha, and run: - Go to the folder /goCaptcha, and run:
@ -37,9 +37,9 @@ user@laptop:~/goCaptcha$ ./goCaptcha
``` ```
### How to make the petitions?
## 2 - How to make the petitions?
1. Get the captcha:
### 2.1 - Get the captcha:
``` ```
GET/ 127.0.0.1:3025/captcha GET/ 127.0.0.1:3025/captcha
``` ```
@ -56,14 +56,20 @@ Server response:
"1b838c46-b784-471e-b143-48be058c39a7.png" "1b838c46-b784-471e-b143-48be058c39a7.png"
], ],
"question": "leopard", "question": "leopard",
"date": ""
"date": "1502274893"
} }
``` ```
2. User selects the images that fit in the 'question' parameter
### 2.2 - User selects the images that fit in the 'question' parameter
(in this case, 'leopard') (in this case, 'leopard')
3. Post the answer. The answer contains the CaptchaId, and an array with the selected images
The selection is stored in an array:
```js
selection=[0,0,1,0,1,0];
```
Where the '1' are the images selected, in the images array order.
### 2.3 - Post the answer. The answer contains the CaptchaId, and an array with the selected images
``` ```
POST/ 127.0.0.1:3025/answer POST/ 127.0.0.1:3025/answer
``` ```
@ -71,7 +77,7 @@ Post example:
```json ```json
{ {
"captchaid": "881c6083-0643-4d1c-9987-f8cc5bb9d5b1", "captchaid": "881c6083-0643-4d1c-9987-f8cc5bb9d5b1",
"selection": [0,0,0,0,1,1]
"selection": [0,0,1,0,1,0]
} }
``` ```
Server response: Server response:
@ -79,9 +85,9 @@ Server response:
true true
``` ```
### How this works?
## 3 - How this works?
###### Server reads dataset
### 3.1 - Server reads dataset
First, server reads all dataset. Dataset is a directory with subdirectories, where each subdirectory contains images of one element. First, server reads all dataset. Dataset is a directory with subdirectories, where each subdirectory contains images of one element.
For example: For example:
@ -104,7 +110,7 @@ imgs/
Then, stores all the filenames corresponding to each subdirectory. So, we have each image and to which element category is (the name of subdirectory). Then, stores all the filenames corresponding to each subdirectory. So, we have each image and to which element category is (the name of subdirectory).
###### Server generates captcha
### 3.2 - Server generates captcha
When server recieves a GET /captcha, generates a captcha, getting random images from the dataset. When server recieves a GET /captcha, generates a captcha, getting random images from the dataset.
For each captcha generated, generates two mongodb models: For each captcha generated, generates two mongodb models:
@ -144,7 +150,8 @@ CaptchaSolution Model
"leopard", "leopard",
"leopard" "leopard"
], ],
"question" : "leopard"
"question" : "leopard",
"date": "1502274893"
} }
``` ```
Both models are stored in the MongoDB. Both models are stored in the MongoDB.
@ -165,7 +172,14 @@ When the server recieves a petition to get an image, recieves the petition with
Captcha Model contains the captcha that server returns to the petition. And CaptchaSolution contains the solution of the captcha. Both have the same Id. Captcha Model contains the captcha that server returns to the petition. And CaptchaSolution contains the solution of the captcha. Both have the same Id.
###### Server validates captcha
### 3.3 - Server validates captcha
When server recieves POST /answer, gets the answer, search for the CaptchaSolution based on the CaptchaId in the MongoDB, and then compares the answer 'selection' parameter with the CaptchaSolution. When server recieves POST /answer, gets the answer, search for the CaptchaSolution based on the CaptchaId in the MongoDB, and then compares the answer 'selection' parameter with the CaptchaSolution.
If the selection is correct, returns 'true', if the selection is not correct, returns 'false'. If the selection is correct, returns 'true', if the selection is not correct, returns 'false'.
## 4 - Security
- If the captcha is resolved in less than 1 second, it's not valid.
- If the captcha is resolved in more than 1 minute, it's not valid.
- The images url, are UUIDs generated each time, in order to give different names for the images each time.

+ 22
- 8
captcha.go

@ -1,9 +1,11 @@
package main package main
import ( import (
"fmt"
"math/rand" "math/rand"
"os/exec" "os/exec"
"strings" "strings"
"time"
"gopkg.in/mgo.v2/bson" "gopkg.in/mgo.v2/bson"
) )
@ -16,10 +18,9 @@ type Captcha struct {
} }
type CaptchaSol struct { type CaptchaSol struct {
Id string `json:"id"` Id string `json:"id"`
Imgs []string `json:"imgs"`
ImgsSolution []string `json:"imgssolution"` ImgsSolution []string `json:"imgssolution"`
Question string `json:"question"` //select all X Question string `json:"question"` //select all X
Date string `json:"date"`
Date int64 `json:"date"`
} }
type CaptchaAnswer struct { type CaptchaAnswer struct {
CaptchaId string `json:"captchaid"` CaptchaId string `json:"captchaid"`
@ -42,6 +43,10 @@ func generateRandInt(min int, max int) int {
//rand.Seed(time.Now().UTC().UnixNano()) //rand.Seed(time.Now().UTC().UnixNano())
return rand.Intn(max-min) + min return rand.Intn(max-min) + min
} }
func generateQuestionFromCategoriesArray(imgs []string) string {
n := generateRandInt(0, len(imgs))
return imgs[n]
}
func generateCaptcha(count int) Captcha { func generateCaptcha(count int) Captcha {
var captcha Captcha var captcha Captcha
var captchaSol CaptchaSol var captchaSol CaptchaSol
@ -60,14 +65,13 @@ func generateCaptcha(count int) Captcha {
err := imgFakePathCollection.Insert(imgFakePath) err := imgFakePathCollection.Insert(imgFakePath)
check(err) check(err)
captcha.Imgs = append(captcha.Imgs, imgFakePath.Fake) captcha.Imgs = append(captcha.Imgs, imgFakePath.Fake)
captchaSol.Imgs = append(captchaSol.Imgs, dataset[categDataset[nCateg]][nImg])
captchaSol.ImgsSolution = append(captchaSol.ImgsSolution, categDataset[nCateg]) captchaSol.ImgsSolution = append(captchaSol.ImgsSolution, categDataset[nCateg])
} }
captcha.Question = "leopard"
captchaSol.Question = "leopard"
err := captchaCollection.Insert(captcha)
check(err)
err = captchaSolCollection.Insert(captchaSol)
question := generateQuestionFromCategoriesArray(captchaSol.ImgsSolution)
captcha.Question = question
captchaSol.Question = question
captchaSol.Date = time.Now().Unix()
err := captchaSolCollection.Insert(captchaSol)
check(err) check(err)
return captcha return captcha
} }
@ -94,5 +98,15 @@ func validateCaptcha(captchaAnswer CaptchaAnswer) bool {
} }
} }
//time elapsed from captcha generation comprovation
date := time.Unix(captchaSol.Date, 0)
elapsed := time.Since(date)
fmt.Println(elapsed.Seconds())
if elapsed.Seconds() < 1 {
solved = false
}
if elapsed.Seconds() > 60 {
solved = false
}
return solved return solved
} }

+ 4
- 0
web/goCaptcha.css

@ -3,6 +3,10 @@
background: #64B5F6!important; background: #64B5F6!important;
color: #ffffff!important; color: #ffffff!important;
} }
.c_red300{
background: #E57373!important;
color: #ffffff!important;
}
.g_button{ .g_button{
border: none; border: none;
border-radius: 2px; border-radius: 2px;

+ 6
- 4
web/goCaptcha.js

@ -29,13 +29,13 @@ function showCaptcha(captcha) {
html = ""; html = "";
html += "<h2>Select all " + captcha.question + "s</h2>"; html += "<h2>Select all " + captcha.question + "s</h2>";
for (k in captcha.imgs) { for (k in captcha.imgs) {
html += "<img id='" + k + "' onclick='select(this)' src='" + goCaptchaURL + "/image/" + captcha.imgs[k] + "' style='width:150px;' />";
html += "<img id='" + k + "' onclick='selectCaptchaImg(this)' src='" + goCaptchaURL + "/image/" + captcha.imgs[k] + "' style='width:150px;cursor:pointer;' />";
} }
html += "<div onclick='validate()' class='g_button c_blue300 g_floatRight'>Validate</div>";
html += "<div onclick='validateCaptcha()' class='g_button c_blue300 g_floatRight'>Validate</div>";
document.getElementById("goCaptcha").innerHTML = html; document.getElementById("goCaptcha").innerHTML = html;
} }
function select(elem) {
function selectCaptchaImg(elem) {
if (selection[elem.id] == 0) { if (selection[elem.id] == 0) {
selection[elem.id] = 1; selection[elem.id] = 1;
document.getElementById(elem.id).className = "g_selected"; document.getElementById(elem.id).className = "g_selected";
@ -45,7 +45,7 @@ function select(elem) {
} }
} }
function validate() {
function validateCaptcha() {
var answer = { var answer = {
selection: selection, selection: selection,
captchaid: captcha.id captchaid: captcha.id
@ -56,7 +56,9 @@ function validate() {
if (resp) { if (resp) {
html += "<h2>goCaptcha validated</h2>"; html += "<h2>goCaptcha validated</h2>";
} else { } else {
selection = [0, 0, 0, 0, 0, 0];
html += "<h2>goCaptcha failed</h2>"; html += "<h2>goCaptcha failed</h2>";
html += "<div onclick='getCaptcha()' class='g_button c_red300 g_floatRight'>Reload Captcha</div>";
} }
document.getElementById("goCaptcha").innerHTML = html; document.getElementById("goCaptcha").innerHTML = html;
} }

Loading…
Cancel
Save