Добавляем QR-код на сайт
QR-код — это специальный цифровой код, представленный в виде изображения, и содержащий закодированную в нем информацию. Нужную информацию из QR-кода можно получить при помощи специальных мобильных приложений или веб-сервисов. Цель использования QR-кодов — это удобство предоставления цифровой информации конечному пользователю. Как правило, их используют на визитках, брошюрах, плакатах, стендах и других оффлайн-средствах предоставления информации. Человек, прочитавший информацию на брошюре, захочет перейти на сайт рекламодателя или записать контактную информацию. Для этого и размещается QR-код, в него помещается любая цифровая информация (ссылки, контакты, адрес), которую пришлось бы долго записывать вручную.
Выглядит QR-код следующим образом:
Большинство современных смартфонов способны легко распознавать подобный код.
Как сделать QR-код
Самый популярный и простой способ сделать QR-код — это воспользоваться специальными веб-сервисами. Например, QR-код можно сгенерировать с помощью сервиса qrcoder.ru.
Если вы хотите стилизовать ваш QR-код под цветовую гамму вашей компании, или просто не хотите, чтобы код выглядел «скучным», можно воспользоваться сервисом qrhacker.com (или сгенерировать черно-белый код и воспользоваться обычным фотошопом). Вот как у меня получилось немного разнообразить стену черно-белых пикселей:
Такой код неплохо впишется в общий дизайн, например, визитки или брошюры компании. Но нужно не забывать, что чем больше вы «разнообразите» свой код различными цветами, тем сильнее уменьшится его читабельность. Слишком раскрашенные QR-коды вряд ли смогут прочесть современные смартфоны, не говоря о старых мобильных устройствах. Поэтому, если основная цель QR-кода — это удобно донести информацию, то не стоит сильно увлекаться его внешним видом.
Как вставить QR код на страницу
По-сути, QR-код — это обычное изображение. И добавить его на страницу можно аналогично обыкновенной картинке:
<img src="qr.png" />
В конструкторе сайтов «Нубекс» QR-код можно добавить на сайт с помощью визуального редактора.
Генерируем QR-код на PHP / Habr
QR-code, уже давно распространен повсеместно, во всех сферах человеческой жизни. Вроде такая популярная вещь, а нормальной библиотеки (Open Source) на PHP — нет. Товарища deltalab, очень напрягла эта проблема и он решил переписать имеющиеся в наличии С библиотеки ibqrencode от Kentaro Fukuchi, на более привычный ему язык PHP.
PHP QR-Code c открытым исходным кодом (LGPL) библиотека для создание QR code и 2-х мерных штрих-кодов. Базируется на коде ibqrencode библиотеки на C. Обеспечивает API для создания штрихкодов в формате PNG, JPEG с помощью GD2. Реализовано на чистом PHP, без каких-либо внешних зависимостей, кроме конечно GD2.
Страничка проекта на sourceforge
UPD:
— Что такое QR можно узнать на из Википедии
— Тематический блог на Хабре, где можно постичь масштабы его распространения
— Генератор «красивых» QR, вставка текста в QR mojiq.kazina.com
— Онлайн QR декодер QRDecoder
— Еще одна реализация QR кодирования на Perl+PHP www.swetake.com/qr/qr_cgi_e.html
— QR code плагин для WordPress anton.shevchuk.name/wordpress/qr-code
— PHP-класс для генерации QR-кода от Павла Новицкого www.e-luge.net/blog/full/655063.html
— MX QR code под ExpressionEngine. Базируется на коде от Swetake — MX QR code
— QR-code модуль для Drupal drupal.org/project/qrs_sheets
— Кодируем в QR с помощь Google Charts API
<img src="https://habrastorage.org/getpro/habr/post_images/de7/8c2/ef8/de78c2ef81511a83d693766568832846.png" />
UPD2:
— Самая лучшая считывалка QR-code с экрана BarShow и лучший генератор BarCapture от Jaxo Systems. Написано на Java так-что для пользователей Linux/MacOS в самый раз, есть и бинарники.
— Расширенная утилита для считывания с Web-камеры bcWebCam
— Еще одна считывалка QR-code прямо с экрана, без телефона QuickMark прямая ссылка ~7mb
nzeraf.com
Использование QR-кодов для быстрого входа на сайт с мобильных устройств / Habr
Если у вас есть сайт, которым часто пользуются с мобильных устройств (таких как телефоны и планшетные ПК), то вы, возможно, задавались вопросом, как реализовать быстрый вход — так, чтобы пользователю не требовалось вводить ни адрес сайта, ни логин и пароль (либо E-mail и пароль).На некоторых сайтах вы, возможно, видели возможность отправить SMS-сообщение со ссылкой для быстрого входа — это, по сути, приблизительно то же самое. Основное отличие описанного в данной заметке подхода в том, что вместо отправки SMS-сообщения мы будем генерировать QR-код, который содержит ссылку, позволяющую войти на сайт без ввода авторизационных данных.
Кстати, весь процесс написания приложения, которое приводится далее, можно посмотреть в скринкасте (есть на YouTube, либо в более хорошем качестве в виде файла MPEG2 в 1080p).
Перед тем, как начать реализовывать этот вариант авторизации, давайте рассмотрим, чем он отличается от варианта с отправкой SMS-сообщения:
- SMS-сообщение получается немного безопаснее: с одной стороны, мы передаём ссылку через третьи стороны (в частности, SMS-гейт, оператор сотовой связи), но с другой стороны, во-первых, ссылка будет недоступна через JS (и, соответственно, даже если на сайте есть XSS, то получить ссылку из SMS-сообщения злоумышленнику не удастся — а вот из QR-кода её получить можно), а во-вторых получить физический доступ к компьютеру с браузером, в котором пользователь авторизован на сайте, в общем случае проще, чем получить доступ к компьютеру, и, одновременно с этим, к телефону пользователя
- SMS-сообщение, в то же время, не настолько универсально: оно не подойдёт, если по какой-то причине нет сотовой связи, либо мобильное устройство, используемое пользователем, вообще не предполагает возможность работы в сотовых сетях (но зато имеет и камеру, и подключение к Интернету, и приложение для сканирования QR-кодов на нём есть или легко устанавливается)
- Отправка SMS-сообщений стоит денег, генерирование QR-кодов абсолютно бесплатно
- У SMS-сообщений в некоторых ситуациях могут значительно падать показатели скорости и надёжности (то есть сообщение может прийти со значительной задержкой, а может даже вообще не прийти), а сканирование QR-кодов предсказуемо и как правило работает хорошо (по крайней мере, если с камерой всё в порядке)
- Для отправки SMS-сообщений сайту необходим номер телефона пользователя, однако далеко не всем пользователям нравится идея вводить свой номер телефона где-либо в Интернете
Получается, что вариант с QR-кодами весьма неплох. И даже если нам важна высокая безопасность, то теоретически никто не мешает отправлять QR-код по электронной почте, или, например, каждый раз запрашивать пароль (лишний раз ввести пароль на удобной большой клавиатуре компьютера, мне кажется, намного проще, чем вводить адрес сайта + логин/адрес электронной почты + пароль на виртуальной клавиатуре мобильного устройства). Тем не менее, сейчас предлагаю реализовать самый простой, базовый вариант быстрого входа по QR-кодам, на реализацию которого нам потребуется минимум времени.
pip install django-qrauth
В этом случае вам останется только включить схему urls приложения в ваш главный urls.py, а также добавить шаблоны. Инструкция по установке, а также исходники вы можете найти на Github.
Ниже описано, как вы можете собрать приложение самостоятельно — актуально, например, в том случае, если вы сразу хотите что-то в нём отредактировать.
Итак, прежде всего перейдём в рабочую директорию Django-проекта, в котором мы хотим добавить такую авторизацию, и создадим новое приложение. Назовём его, например, qrauth:
python manage.py startapp qrauth
В появившейся директории создадим файл qr.py:
try: from PIL import Image, ImageDraw except ImportError: import Image, ImageDraw import qrcode.image.base import qrcode.image.pil class PilImage(qrcode.image.pil.PilImage): def __init__(self, border, width, box_size): if Image is None and ImageDraw is None: raise NotImplementedError("PIL not available") qrcode.image.base.BaseImage.__init__(self, border, width, box_size) self.kind = "PNG" pixelsize = (self.width + self.border * 2) * self.box_size self._img = Image.new("RGBA", (pixelsize, pixelsize)) self._idr = ImageDraw.Draw(self._img) def make_qr_code(string): return qrcode.make(string, box_size=10, border=1, image_factory=PilImage)
Здесь используется модуль python-qrcode. Установить его можно с помощью pip:
pip install qrcode
Для того, чтобы получались картинки с прозрачным (а не белым) фоном, мы специально используем свой класс для создания картинок, наследуя его от qrcode.image.pil.PilImage. Если вас устраивают картинки с белым фоном, то достаточно будет написать так:
import qrcode
def make_qr_code(string):
return qrcode.make(string, box_size=10, border=1)
Стоит отметить, что в данном случае картинки, которые возвращает qrcode.make (и, соответственно, функция make_qr_code) неоптимальны с точки зрения размера. Например, с помощью optipng их размер удаётся уменьшить примерно на 70% (разумеется, без потери качества). Тем не менее, в большинстве случаев это непринципиально — их размер в любом случае получается небольшим (в пределах нескольких кибибайтов).
Далее создадим файл utils.py и добавим функции, которые затем будем использовать в представлениях (views):
import os
import string
import hashlib
from django.conf import settings
def generate_random_string(length,
stringset="".join(
[string.ascii_letters+string.digits]
)):
"""
Returns a string with `length` characters chosen from `stringset`
>>> len(generate_random_string(20) == 20
"""
return "".join([stringset[i%len(stringset)] \
for i in [ord(x) for x in os.urandom(length)]])
def salted_hash(string):
return hashlib.sha1(":)".join([
string,
settings.SECRET_KEY,
])).hexdigest()
Функция generate_random_string генерирует строку случайных символов заданной длины. По умолчанию строка составляется из букв латинского алфавита (как нижнего, так и верхнего регистра) и цифр.
Функция salted_hash солит и хэширует строку.
Теперь откроем views.py и напишем представления:
import redis
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, get_backends
from django.contrib.sites.models import get_current_site
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from privatemessages.context_processors import \
number_of_new_messages_processor
from utils import generate_random_string, salted_hash
from qr import make_qr_code
@login_required
def qr_code_page(request):
r = redis.StrictRedis()
auth_code = generate_random_string(50)
auth_code_hash = salted_hash(auth_code)
r.setex(auth_code_hash, 300, request.user.id)
return render_to_response("qrauth/page.html",
{"auth_code": auth_code},
context_instance=RequestContext(request))
@login_required
def qr_code_picture(request, auth_code):
r = redis.StrictRedis()
auth_code_hash = salted_hash(auth_code)
user_id = r.get(auth_code_hash)
if (user_id == None) or (int(user_id) != request.user.id):
raise Http404("No such auth code")
current_site = get_current_site(request)
scheme = request.is_secure() and "https" or "http"
login_link = "".join([
scheme,
"://",
current_site.domain,
reverse("qr_code_login", args=(auth_code_hash,)),
])
img = make_qr_code(login_link)
response = HttpResponse(mimetype="image/png")
img.save(response, "PNG")
return response
def login_view(request, auth_code_hash):
r = redis.StrictRedis()
user_id = r.get(auth_code_hash)
if user_id == None:
return HttpResponseRedirect(reverse("invalid_auth_code"))
r.delete(auth_code_hash)
try:
user = User.objects.get(id=user_id)
except User.DoesNotExist:
return HttpResponseRedirect(reverse("invalid_auth_code"))
# In lieu of a call to authenticate()
backend = get_backends()[0]
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
login(request, user)
return HttpResponseRedirect(reverse("dating.views.index"))
При обращении к странице с QR-кодом (qr_code_page) генерируется случайная строка из 50 символов. Далее в Redis (установить клиент можно с помощью
pip install redis
) добавляется новая пара ключ-значение, где в качестве ключа задаётся солёный хэш сгенерированной случайной строки, а в качестве значения — идентификатор пользователя (это нужно для того, чтобы картинка с QR-кодом, которая добавляется на страницу, была доступна только этому пользователю). Это этого ключа устанавливается время истечения, в примере указано 300 секунд (5 минут).В контексте шаблона при этом задаётся сгенерированная случайная строка: эта строка затем используется в адресе, по которому возвращается картинка с QR-кодом (а вот для авторизации как раз используется хэш, и в QR-код включается именно адрес с хэшем: таким образом, даже если кому-то ещё становится известен адрес картинки, то для авторизации этого будет недостаточно — для авторизации нужно знать солёный хэш для случайной строки, указанной в адресе картинки).
Далее, при загрузке картинки (qr_code_picture) случайная строка, содержащаяся в адресе картинки, опять же, хэшируется, и затем проверяется, есть ли в Redis соответствующий ключ. Если такой ключ есть, и содержит идентификатор текущего пользователя, то создаётся и возвращается QR-код, содержащий абсолютную ссылку для мгновенной авторизации на сайте. В ином случае возвращается ошибка 404.
Кстати, понимаете, что здесь можно легко улучшить?При выполненииint(user_id) != request.user.id
может возникнуть ValueError — в том случае, если в Redis есть такой ключ, но его значение не подходит для преобразования к десятичному целому числу. Решается с помощью try…except, либо с помощью строкового метода isdigit. Либо можно наоборот получать строку от request.user.id и сравнивать её с полученным значением ключа.Также можно использовать не просто хэш, а, например, хэш с префиксом — особенно актуально в том случае, если где-то в другом месте тоже создаются аналогичные ключи.
Получение домена здесь происходит с помощью django.contrib.sites. Указать домен можно через административный интерфейс (/admin/sites/site/).
Если ваш сервер находится за reverse proxy (например, nginx), и вы используете SSL, то убедитесь, что информация об этом включается в запросы к upstream-серверу — это нужно для того, чтобы request.is_secure() выдавал правильное значение (для этого определите в настройках SECURE_PROXY_SSL_HEADER, но учитывайте, что вам нужно будет обязательно устанавливать/удалять этот заголовок на стороне прокси-сервера — иначе, если, например, ваш сайт доступен и по HTTP, и по HTTPS, то пользователь, который заходит по HTTP, сможет установить этот заголовок таким образом, что request.is_secure() будет выдавать значение True, а это плохо с точки зрения безопасности).
И да, начиная с Python 2.6 вместо request.is_secure() and "https" or "http"
можно писать "https" if request.is_secure() else "http"
.
При переходе по ссылке для мгновенной авторизации проверяется, есть ли в Redis ключ, соответствующий указанному в ссылке хэшу. Если нет — пользователь перенаправляется на страницу с сообщением о том, что QR-код недействителен (в данном примере эта страница не требует написания отдельного представления). Если есть — то ключ в Redis удаляется, после чего проверяется, есть ли в базе данных пользователь с таким идентификатором. Если нет — опять же, происходит перенаправление на страницу с сообщением о том, что QR-код недействителен. Если есть — то происходит авторизация и пользователь перенаправляется на главную страницу сайта.
Теперь добавим файл urls.py и определим в нём схему URL приложения:
from django.conf.urls import patterns, url
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('qrauth.views',
url(
r'^pic/(?P<auth_code>[a-zA-Z\d]{50})/$',
'qr_code_picture',
name='auth_qr_code'
),
url(
r'^(?P<auth_code_hash>[a-f\d]{40})/$',
'login_view',
name='qr_code_login'
),
url(
r'invalid_code/$',
direct_to_template,
{'template': 'qrauth/invalid_code.html'},
name='invalid_auth_code'
),
url(
r'^$',
'qr_code_page',
name='qr_code_page'
),
)
Также не забудьте открыть ваш главный urls.py (который указывается в ROOT_URLCONF), и включить туда urlpatterns из urls.py созданного приложения:
urlpatterns = patterns('',
# …
url(r'^qr/', include('qrauth.urls')),
# …
)
Теперь откройте директорию с шаблонами и добавьте туда каталог qrauth.
Пример для invalid_code.html:
{% extends "base.html" %}
{% block title %}QR-код недействителен{% endblock %}
{% block content %}
<div>
<h2>QR-код недействителен</h2>
<p>QR-код, который вы используете для авторизации, недействителен. Пожалуйста, попробуйте ещё раз открыть страницу с QR-кодом для входа и отсканировать код повторно.</p>
</div>
{% endblock %}
Пример для page.html:
{% extends "base.html" %}
{% block title %}QR-код для входа{% endblock %}
{% block content %}
<div>
<h2>QR-код для входа</h2>
<p>Для быстрого входа на сайт с мобильного устройства (например, телефона или планшета) отсканируйте этот QR-код:</p>
<div><img src="{% url auth_qr_code auth_code %}" alt="QR"></div>
<p>Каждый сгенерированный QR-код работает только один раз и только 5 минут. Если вам требуется другой QR-код, то просто откройте <a href="{% url qr_code_page %}">эту страницу</a> снова.</p>
</div>
{% endblock %}
Собственно, теперь остаётся открыть сайт в браузере и проверить. Если QR-код успешно генерируется и отображается, попробуйте сосканировать его с помощью телефона или ещё чего-нибудь с камерой и Интернетом.
Если будут какие-то вопросы или мысли о том, какие ещё могут быть варианты для быстрой и удобной авторизации с мобильных устройств — буду рад комментариям.
Всем удачи и приятного программирования!
С наступающим вас летом! 🙂
2QR или Как сохранить ссылку в телефон / Habr
Введение
Хотя на улице эпоха нетбуков и флешек, некоторым из нас иногда приходится час-другой поработать за чужим или, хуже того, «общественным» компьютером, будь то в гостях, в универе или в интернет-кафе. Однако, когда дело доходит до сохранения результатов, здоровая паранойя подсказывает, что лучше воздержаться от использования своей флешки с ценными данными, и тем более — отправки файлов самому себе на почту: кто знает, что за киберпаразиты обитают на этом компьютере…
К счастью, в сети есть множество сервисов, позволяющих анонимно выложить свои файлы. Не нужен аккаунт — значит, нет риска «засветить» свои пароли трояну. Однако возникает вопрос: как донести до своего компьютера сам адрес выложенного файла?
Существующие варианты
Можно, конечно, просто записать его на бумагу. Правда, её сначала придётся найти, а потом — постараться не потерять. Ненадёжно, да и несолидно как-то, не по-айтишному… Лучше было бы сохранить ссылку в мобильнике, который и всегда с собой, и потерять его сложнее. Вот только вбивать длиннющий адрес с телефонной клавиатуры — это не пупырышки на пакетиках давить, а долго и утомительно, даже с qwerty-клавиатурой.
QR-коды, уже упоминавшиеся на хабре, позволяют быстро и эффект(ив)но отправить ссылку на телефон прямо с экрана монитора. Я уже описывал расширение для Firefox, которое создаёт QR-код для текущей страницы. Разумеется, далеко не на каждом компьютере стоит FF, да и установка расширения ради одного раза, во-первых, не везде возможна, а во-вторых — всё-таки перебор. В таких случаях можно использовать онлайн-генераторы QR-кодов (например, kaywa или i-nigma). В этом случае придётся вспоминать/искать адрес генератора, вставлять в него ссылку… Слишком много лишних движений.
Предлагаемое решение
Чтобы упростить процесс, я сделал небольшой сервис для создания QR-кодов. Способ использования очень прост: в адресной строке браузера, перед адресом текущей страницы допишите 2qr.ru/ и нажмите Enter — и вы получите QR-код, соответствующий этой странице. Останется навести на него камеру телефона со считывающей программой, и вуаля — ссылка у вас с собой, можно её сохранить в закладках, отправить по sms/email, или просто открыть в мобильном браузере.
Интерфейс минимален — вся работа с сервисом осуществляется через адресную строку браузера. 2qr.ru без параметров отобразит небольшую справку по пользованию сервисом. Сама картинка QR-кода генерится с помощью Google Charts (то есть, по идее, бóльшая часть хабраэффекта должна лечь на могучие сервера гугла).
В отличие от упомянутых онлайн-генераторов QR-кодов от kaywa и i-nigma, 2QR.ru имеет короткий интуитивно-понятный адрес и минималистичный command-line address-bar интерфейс, работает при отключенных Javascript’ах, и поддерживает кириллицу в ссылках.
Считывание QR-кодов
Программы для распознавания QR-кодов существуют для самых разных платформ, включая Windows Mobile, iPhone, Symbian и просто телефоны с J2ME. Скачать некоторые из этих программ можно по этим адресам:
QuickMark (login/pass: habr)
i-nigma (чтобы скачать, зайдите с телефона на i-nigma.mobi)
Kaywa (чтобы скачать, зайдите с телефона на reader.kaywa.com/mobile)
О других программах можно почитать, например, в этом или этом обзорах (по-английски). Можно также посмотреть Excel-файл со списком различных моделей телефонов и адресов для скачивания совместимых с ними программ.
Заключение
В топике был представлен 2QR.ru — сервис для быстрого преобразования URL-адресов в QR-коды. В отличие от конкурентов, 2QR.ru имеет легкозапоминающийся адрес, прямой интерфейс через адресную строку, работает при отключенных Javascript’ах и поддерживает кириллицу в ссылках.
В будущем, если это будет кому-то нужно, планируется добавить другие входные форматы: преобразование в QR-код телефонных номеров, визитных карточек, смс-сообщений и просто коротких текстов.
Благодарности
cb93ka — за новость о распродаже трёхсимвольных доменов.
Google — за Charts API и поддержку им QR кодов.
Алфавиту — за любезно предоставленные буквы 🙂
Upd: Я незаслуженно забыл платформу Android, для неё тоже есть программы распознавания QR-кодов: Barcode Scanner, ixMAT Code Scanner, BeeTagg, Zxing (спасибо razr, ravve).
Другие способы сохранить ссылку:
- Если позволяют возможности камеры, можно просто сфотографировать кусок экрана со ссылкой (спасибо null, Vodkin).
- Если камера не умеет делать макроснимки — сократить ссылку сервисом вроде tinyurl, затем вывести крупным шрифтом на экран, и тоже сфотографировать (спасибо piroJOKE). Подойдёт тем, кто не любит QR-коды или не имеет под рукой программы для считывания QR-кодов.
- Можно отправить себе ссылку посредством SMS с сайта опсоса, если такой сервис имеется (спасибо Ackrite). Пароли в безопасности, но выдаёте свой телефонный номер.
- Создать одноразовый почтовый ящик, и переслать с него на свой личный все ссылки (спасибо UpRight).
- Отправить себе на IM, используя временный аккаунт и онлайн-сервис типа meebo.com (спасибо estum).
- Использовать один из social bookmarking сервисов и отдельный аккаунт (спасибо knja).
Upd2: Спасибо shtirlic, который написал букмарклет, показывающий QR-код прямо поверх исходной страницы.