mirror of
https://github.com/arnaucube/goCaptcha.git
synced 2026-02-06 19:16:44 +01:00
implemented captcha time validation on backend, added reload captcha option in javascript library
This commit is contained in:
42
README.md
42
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?
|
## 1 - How to use?
|
||||||
#### Frontend
|
### 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:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 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.
|
||||||
|
|||||||
30
captcha.go
30
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"
|
question := generateQuestionFromCategoriesArray(captchaSol.ImgsSolution)
|
||||||
captchaSol.Question = "leopard"
|
captcha.Question = question
|
||||||
err := captchaCollection.Insert(captcha)
|
captchaSol.Question = question
|
||||||
check(err)
|
captchaSol.Date = time.Now().Unix()
|
||||||
err = captchaSolCollection.Insert(captchaSol)
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user