3 Commits

Author SHA1 Message Date
5ea5d4d0ba Merge pull request 'Version 0.7.0' (#1) from develop into main
Reviewed-on: #1
2023-12-08 21:18:22 +06:00
e72dc03589 Update README with project specifics.
The README file has been updated to provide specific details about the current project.
2023-12-08 21:15:51 +06:00
6bf2bc793b Add Docker setup for production environment. 2023-12-08 21:10:31 +06:00
7 changed files with 377 additions and 45 deletions

View File

@@ -1,66 +1,50 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
## О проекте
<p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
Захотелось написать свой независимый сервис защиты от роботов. Сервис каптча написан на фреймворке Laravel. Вдохновлялся, а так же брал картинки с проекта <a href="https://github.com/wenlng/go-captcha" target="_blank">Go Captcha</a>.
## About Laravel
## Зависимости
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
php 8.2 (модули: redis, gd)
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
redis
Laravel is accessible, powerful, and provides tools required for large, robust applications.
mysql 8
## Learning Laravel
## Демострация
Демо сервис каптча: https://captcha-admin-demo.tut-site.net/
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
Email: demo@tut-site.net
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
Пароль: demodemo
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 2000 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
Демо каптча: https://captcha-demo.tut-site.net/
## Laravel Sponsors
## API
https://captcha-admin-demo.tut-site.net/api-docs/
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
## Javascript клиент для сайта
https://git.kor-elf.net/kor-elf/captcha-rule-for-laravel
### Premium Partners
## Как проверять со стороны бэкенда
Для Laravel 10 есть готовый пакет: https://git.kor-elf.net/kor-elf/captcha-rule-for-laravel
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
- **[Lendio](https://lendio.com)**
Можно установить этот пакет так: composer require kor-elf/captcha-rule-for-laravel
## Contributing
<br><b>Curl:</b>
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
curl -X POST 'https://captcha-admin-demo.tut-site.net/api/v1/captcha/{captcha-token}' -H 'private-token: {your-private-token}' -H 'Content-Type: application/json' -d '{"user_agent": "{user-agent}"}' --max-time 10
## Code of Conduct
Где {captcha-token} - токен получил пользователь от сервиса каптча после успешной проверки.
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
Где {your-private-token} - приватный токен, который мы создали в админке.
## Security Vulnerabilities
Где {user-agent} - передаём user agent от пользователя, который проходил каптчу.
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
Успешная проверка пользователя вернёт ответ код 200 и status = true. Иначе считаем, что пользователь не прошёл проверку на робота.
## License
## Репозиторий с демо
https://git.kor-elf.net/kor-elf/service-captcha-demo
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
## Лицензия
[MIT license](https://opensource.org/licenses/MIT).

42
docker-compose-prod.yml Normal file
View File

@@ -0,0 +1,42 @@
version: '3.7'
services:
nginx:
build:
context: ./docker/nginx
dockerfile: Dockerfile
depends_on:
- app
- swagger
ports:
- ${DOCKER_CAPTCHA_NGINX_PORT}:80
app:
depends_on:
- redis
build:
context: ./docker/app
dockerfile: Dockerfile
target: PRODUCTION
# restart: always
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
- CHOWN
- FOWNER
ports:
- "9000"
env_file: .env
volumes:
- /etc/localtime:/etc/localtime:ro
swagger:
image: swaggerapi/swagger-ui
depends_on:
- app
environment:
URLS: "[ { url: '/swagger.json', name: '/swagger.json' } ]"
BASE_URL: /api-docs
ports:
- "8080"
redis:
image: redis:3.0-alpine

87
docker/app/Dockerfile Normal file
View File

@@ -0,0 +1,87 @@
FROM docker.io/php:8.2-zts-alpine3.18 AS UNIT_BUILDER
ARG UNIT_VERSION=1.31.1
RUN apk --no-cache add pcre2-dev gcc git musl-dev make && \
mkdir -p /usr/lib/unit/modules && \
git clone https://github.com/nginx/unit.git && \
cd unit && \
git checkout $UNIT_VERSION && \
./configure --prefix=/var --statedir=/var/lib/unit --runstatedir=/var/run --control=unix:/run/unit/control.unit.sock --log=/var/log/unit.log --user=www-data --group=www-data --tmpdir=/tmp --modulesdir=/var/lib/unit/modules && \
./configure php && \
make && \
make install
FROM docker.io/php:8.2-zts-alpine3.18 as BUILD
COPY --from=UNIT_BUILDER /var/sbin/unitd /usr/sbin/unitd
COPY --from=UNIT_BUILDER /var/lib/unit/ /var/lib/unit/
COPY docker-entrypoint.sh /home/unit/docker-entrypoint.sh
COPY unit-config.json /docker-entrypoint.d/config.json
RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freetype oniguruma libzip \
&& apk add --no-cache --virtual .phpize-deps icu-dev libpng-dev bzip2-dev libwebp-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libzip-dev pcre2-dev ${PHPIZE_DEPS} \
&& docker-php-ext-configure intl --enable-intl && \
docker-php-ext-configure bcmath --enable-bcmath && \
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp && \
docker-php-ext-install -j$(nproc) gd && \
docker-php-ext-install bcmath &&\
docker-php-ext-install pdo \
mysqli pdo_mysql \
intl mbstring \
zip pcntl \
exif opcache bz2 \
calendar \
&& pear update-channels && pecl update-channels \
&& pecl install redis && docker-php-ext-enable redis \
&& rm -rf /tmp/pear \
&& docker-php-source delete \
&& apk del .phpize-deps \
&& rm -rf /var/cache/apk/* && rm -rf /etc/apk/cache \
&& rm -rf /usr/share/php && rm -rf /tmp/* \
&& rm "$PHP_INI_DIR/php.ini-development" \
&& mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& mkdir -p /tmp/php/upload \
&& mkdir -p /tmp/php/sys \
&& mkdir -p /tmp/php/session \
&& chown -R www-data:www-data /tmp/php \
&& ln -sf /dev/stdout /var/log/unit.log \
&& addgroup -S unit && adduser -S unit -G unit \
&& chmod 755 /home/unit/docker-entrypoint.sh
FROM BUILD as APP_BUILD_FOR_PRODUCTION
WORKDIR /home/app
RUN apk --no-cache add git nodejs npm \
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& git clone https://git.kor-elf.net/kor-elf/service-captcha.git . \
&& composer install --optimize-autoloader --no-dev \
&& npm install && npm run build \
&& rm -rf /home/app/node_modules /home/app/.git /home/app/docker
#
FROM BUILD AS PRODUCTION
COPY --from=APP_BUILD_FOR_PRODUCTION /home/app /var/www/html
WORKDIR /var/www/html
STOPSIGNAL SIGTERM
ENTRYPOINT ["/home/unit/docker-entrypoint.sh"]
EXPOSE 9000
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock", "--user", "unit", "--group", "unit"]
#
FROM BUILD AS DEVELOP
WORKDIR /var/www/html
STOPSIGNAL SIGTERM
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
ENTRYPOINT ["/home/unit/docker-entrypoint.sh"]
EXPOSE 9000
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock", "--user", "unit", "--group", "unit"]

View File

@@ -0,0 +1,111 @@
#!/bin/sh
set -euo pipefail
WAITLOOPS=5
SLEEPSEC=1
unitd="unitd"
curl_put()
{
RET=$(/usr/bin/curl -s -w '%{http_code}' -X PUT --data-binary @$1 --unix-socket /var/run/control.unit.sock http://localhost/$2)
RET_BODY=$(echo $RET | /bin/sed '$ s/...$//')
RET_STATUS=$(echo $RET | /usr/bin/tail -c 4)
if [ "$RET_STATUS" -ne "200" ]; then
echo "$0: Error: HTTP response status code is '$RET_STATUS'"
echo "$RET_BODY"
return 1
else
echo "$0: OK: HTTP response status code is '$RET_STATUS'"
echo "$RET_BODY"
fi
return 0
}
if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then
echo "$0: Launching Unit daemon to perform initial configuration..."
/usr/sbin/$unitd --control unix:/var/run/control.unit.sock
for i in $(/usr/bin/seq $WAITLOOPS); do
if [ ! -S /var/run/control.unit.sock ]; then
echo "$0: Waiting for control socket to be created..."
/bin/sleep $SLEEPSEC
else
break
fi
done
# even when the control socket exists, it does not mean unit has finished initialisation
# this curl call will get a reply once unit is fully launched
/usr/bin/curl -s -X GET --unix-socket /var/run/control.unit.sock http://localhost/
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then
echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..."
echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do
echo "$0: Uploading certificates bundle: $f"
curl_put $f "certificates/$(basename $f .pem)"
done
echo "$0: Looking for JavaScript modules in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.js"); do
echo "$0: Uploading JavaScript module: $f"
curl_put $f "js_modules/$(basename $f .js)"
done
echo "$0: Looking for configuration snippets in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.json"); do
echo "$0: Applying configuration $f";
curl_put $f "config"
done
if [ ! -z ${UNIT_SOURCE+x} ]
then
echo "[${UNIT_SOURCE}]" > /docker-entrypoint.d/unit_source.json
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
fi
echo "$0: Looking for shell scripts in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do
echo "$0: Launching $f";
"$f"
done
# warn on filetypes we don't know what to do with
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -not -name "*.sh" -not -name "*.json" -not -name "*.pem" -not -name "*.js"); do
echo "$0: Ignoring $f";
done
fi
echo "$0: Stopping Unit daemon after initial configuration..."
kill -TERM $(/bin/cat /var/run/unit.pid)
for i in $(/usr/bin/seq $WAITLOOPS); do
if [ -S /var/run/control.unit.sock ]; then
echo "$0: Waiting for control socket to be removed..."
/bin/sleep $SLEEPSEC
else
break
fi
done
if [ -S /var/run/control.unit.sock ]; then
kill -KILL $(/bin/cat /var/run/unit.pid)
rm -f /var/run/control.unit.sock
fi
echo
echo "$0: Unit initial configuration complete; ready for start up..."
echo
fi
php artisan config:cache
php artisan event:cache
php artisan route:cache
php artisan view:cache
php artisan migrate --force
chown -R unit:unit /var/www/html
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
chmod -R 777 /var/www/html/storage /var/www/html/bootstrap/cache
exec "$@"

View File

@@ -0,0 +1,69 @@
{
"listeners": {
"*:9000": {
"pass": "routes",
"forwarded": {
"client_ip": "X-Forwarded-For",
"recursive": false,
"source": [
]
}
}
},
"routes": [
{
"match": {
"uri": [
"/index.php/",
"~^/index\\.php/.*",
"~\\.php$"
]
},
"action": {
"return": 404
}
},
{
"action": {
"share": "/var/www/html/public$uri",
"fallback": {
"pass": "applications/laravel"
}
}
}
],
"applications": {
"laravel": {
"type": "php",
"root": "/var/www/html/public",
"working_directory": "/var/www/html",
"user": "www-data",
"group": "www-data",
"script": "index.php",
"processes": {
"max": 10,
"spare": 5,
"idle_timeout": 20
},
"options": {
"file": "/usr/local/etc/php/php.ini",
"admin": {
"upload_tmp_dir": "/tmp/php/upload",
"sys_temp_dir": "/tmp/php/sys",
"session.save_path": "/tmp/php/session",
"open_basedir": "/var/www/html:/tmp/php:.",
"memory_limit": "256M",
"upload_max_filesize": "20M",
"post_max_size": "20M",
"expose_php": "0"
},
"user": {
"display_errors": "0"
}
}
}
}
}

3
docker/nginx/Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM nginx:alpine3.18-slim
COPY nginx.conf /etc/nginx/conf.d/default.conf

36
docker/nginx/nginx.conf Normal file
View File

@@ -0,0 +1,36 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name captcha;
client_max_body_size 1024M;
root /var/www/html/public;
location / {
location /api-docs {
proxy_pass http://swagger:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
}
location / {
proxy_pass http://app:9000;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
}
}
}