Безрассудный logout html view. Представления log in и log out. Подборка полезных ссылок по сабжу
Django comes with a lot of built-in resources for the most common use cases of a Web application. The registration app
is a very good example and a good thing about it is that the features can be used out-of-the-box.
With the Django registration app you can take advantages of the following features:
Login
Logout
Sign up
Password reset
In this tutorial we will focus in the Login and Logout features. For sign up and password reset, check the tutorials
below:
Getting started
Before we start, make sure you have django.contrib.auth in your INSTALLED_APPS and the authentication middleware
properly configured in the MIDDLEWARE_CLASSES settings.
Both come already configured when you start a new Django project using the command startproject . So if you did not
remove the initial configurations you should be all set up.
In case you are starting a new project just to follow this tutorial, create a user using the command line just so we
can test the login and logout pages.
$
python manage.py createsuperuser
In the end of this article I will provide the source code of the example with the minimal configuration.
Configure the URL routes
First import the django.contrib.auth.views module and add a URL route for the login and logout views:
from
django.conf.urls
import
url
from
django.contrib
import
admin
from
django.contrib.auth
import
views
as
auth_views
urlpatterns
=
[
url
(r"^login/$"
,
auth_views
.
login
,
name
=
"login"
),
url
(r"^logout/$"
,
auth_views
.
logout
,
name
=
"logout"
),
url
(r"^admin/"
,
admin
.
site
.
urls
),
]
Create a login template
By default, the django.contrib.auth.views.login view will try to render the registration/login.html template. So
the basic configuration would be creating a folder named registration and place a login.html template inside.
This simple example already validates username and password and authenticate correctly the user.
Customizing the login view
There are a few parameters you can pass to the login view to make it fit your project. For example, if you want to
store your login template somewhere else than registration/login.html you can pass the template name as a parameter:
You can also pass a custom authentication form using the parameter authentication_form , incase you have implemented
a custom user model.
Now, a very important configuration is done in the settings.py file, which is the URL Django will redirect the user
after a successful authentication.
Inside the settings.py file add:
LOGIN_REDIRECT_URL
=
"home"
The value can be a hardcoded URL or a URL name. The default value for LOGIN_REDIRECT_URL is /accounts/profile/ .
It is also important to note that Django will try to redirect the user to the next GET param.
Setting up logout view
After acessing the django.contrib.auth.views.logout view, Django will render the registration/logged_out.html
template. In a similar way as we did in the login view, you can pass a different template like so:
Usually I prefer to use the next_page parameter and redirect either to the homepage of my project or to the login
page when it makes sense.
Многие начинают писать проект для работы с единственной задачей, не подразумевая, что это может вырасти в многопользовательскую систему управления, ну допустим, контентом или упаси бог, производством. И всё вроде здорово и классно, всё работает, пока не начинаешь понимать, что тот код, который написан — состоит целиком и полностью из костылей и хардкода. Код перемешанный с версткой, запросами и костылями, неподдающийся иногда даже прочтению. Возникает насущная проблема: при добавлении новых фич, приходится с этим кодом очень долго и долго возиться, вспоминая «а что же там такое написано то было?» и проклинать себя в прошлом.
Вы можеть быть даже слышали о шаблонах проектирования и даже листали эти прекрасные книги:
Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидесс «Приемы объектно ориентированного проектирования. Паттерны проектирования»;
М. Фаулер «Архитектура корпоративных программных приложений».
А многие, не испугавшись огромных руководств и документаций, пытались изучить какой-либо из современных фреймворков и столкнувшись со сложностью понимания (в силу наличия множества архитектруных концепций хитро увязанных между собой) отложили изучение и применение современных интсрументов в «долгий ящик».
Представленная статья будет полезна в первую очередь новичкам. Во всяком случае, я надеюсь что за пару часов вы сможете получить представление о реализации MVC паттерна, который лежит в основе всех современных веб-фреймворков, а также получить «пищу» для дальнейших размышлений над тем — «как стоит делать». В конце статьи приводится подборка полезных ссылок, которые также помогут разобраться из чего состоят веб-фреймворки (помимо MVC) и как они работают.
Прожженные PHP-программисты вряд ли найдут в данной статье что-то новое для себя, но их замечания и комментарии к основному тексту были бы очень кстати! Т.к. без теории практика невозможна, а без практики теория бесполезна, то сначала будет чуть-чуть теории, а потом перейдем к практике. Если вы уже знакомы с концепцией MVC, можете пропустить раздел с теорией и сразу перейти к практике.
1. Теория
Шаблон MVC описывает простой способ построения структуры приложения, целью которого является отделение бизнес-логики от пользовательского интерфейса. В результате, приложение легче масштабируется, тестируется, сопровождается и конечно же реализуется.
Рассмотрим концептуальную схему шаблона MVC (на мой взгляд — это наиболее удачная схема из тех, что я видел):
В архитектуре MVC модель предоставляет данные и правила бизнес-логики, представление отвечает за пользовательский интерфейс, а контроллер обеспечивает взаимодействие между моделью и представлением.
Типичную последовательность работы MVC-приложения можно описать следующим образом:
При заходе пользователя на веб-ресурс, скрипт инициализации создает экземпляр приложения и запускает его на выполнение. При этом отображается вид, скажем главной страницы сайта.
Приложение получает запрос от пользователя и определяет запрошенные контроллер и действие. В случае главной страницы, выполняется действие по умолчанию (index
).
Приложение создает экземпляр контроллера и запускает метод действия, в котором, к примеру, содержаться вызовы модели, считывающие информацию из базы данных.
После этого, действие формирует представление с данными, полученными из модели и выводит результат пользователю.
Модель
— содержит бизнес-логику приложения и включает методы выборки (это могут быть методы ORM), обработки (например, правила валидации) и предоставления конкретных данных, что зачастую делает ее очень толстой, что вполне нормально. Модель не должна напрямую взаимодействовать с пользователем. Все переменные, относящиеся к запросу пользователя должны обрабатываться в контроллере. Модель не должна генерировать HTML или другой код отображения, который может изменяться в зависимости от нужд пользователя. Такой код должен обрабатываться в видах. Одна и та же модель, например: модель аутентификации пользователей может использоваться как в пользовательской, так и в административной части приложения. В таком случае можно вынести общий код в отдельный класс и наследоваться от него, определяя в наследниках специфичные для подприложений методы.
Вид
— используется для задания внешнего отображения данных, полученных из контроллера и модели. Виды cодержат HTML-разметку и небольшие вставки PHP-кода для обхода, форматирования и отображения данных. Не должны напрямую обращаться к базе данных. Этим должны заниматься модели. Не должны работать с данными, полученными из запроса пользователя. Эту задачу должен выполнять контроллер. Может напрямую обращаться к свойствам и методам контроллера или моделей, для получения готовых к выводу данных. Виды обычно разделяют на общий шаблон, содержащий разметку, общую для всех страниц (например, шапку и подвал) и части шаблона, которые используют для отображения данных выводимых из модели или отображения форм ввода данных.
Контроллер
— связующее звено, соединяющее модели, виды и другие компоненты в рабочее приложение. Контроллер отвечает за обработку запросов пользователя. Контроллер не должен содержать SQL-запросов. Их лучше держать в моделях. Контроллер не должен содержать HTML и другой разметки. Её стоит выносить в виды. В хорошо спроектированном MVC-приложении контроллеры обычно очень тонкие и содержат только несколько десятков строк кода. Чего, не скажешь о Stupid Fat Controllers (SFC) в CMS Joomla. Логика контроллера довольно типична и большая ее часть выносится в базовые классы. Модели, наоборот, очень толстые и содержат большую часть кода, связанную с обработкой данных, т.к. структура данных и бизнес-логика, содержащаяся в них, обычно довольно специфична для конкретного приложения.
1.1. Front Controller и Page Controller
В большинстве случае, взаимодействие пользователя с web-приложением проходит посредством переходов по ссылкам. Посмотрите сейчас на адресную строку браузера — по этой ссылке вы получили данный текст. По другим ссылкам, например, находящимся справа на этой странице, вы получите другое содержимое. Таким образом, ссылка представляет конкретную команду web-приложению.
Надеюсь, вы уже успели заметить, что у разных сайтов могут быть совершенные разные форматы построения адресной строки. Каждый формат может отображать архитектуру web-приложения. Хотя это и не всегда так, но в большинстве случаев это явный факт.
Рассмотрим два варианта адресной строки, по которым показывается какой-то текст и профиль пользователя.
Первый вариант:
www.example.com/article.php?id=3
www.example.com/user.php?id=4
Здесь каждый сценарий отвечает за выполнение определённой команды.
Второй вариант:
www.example.com/index.php?article=3
www.example.com/index.php?user=4
А здесь все обращения происходят в одном сценарии index.php
.
Подход с множеством точек взаимодействия вы можете наблюдать на форумах с движком phpBB. Просмотр форума происходит через сценарий viewforum.php
, просмотр топика через viewtopic.php
и т.д. Второй подход, с доступом через один физический файл сценария, можно наблюдать в моей любимой CMS MODX, где все обращения проходят черезindex.php
.
Эти два подхода совершенно различны. Первый — характерен для шаблона контроллер страниц (Page Controller), а второй подход реализуется паттерном контроллер запросов (Front Controller). Контроллер страниц хорошо применять для сайтов с достаточно простой логикой. В свою очередь, контроллер запросов объединяет все действия по обработке запросов в одном месте, что даёт ему дополнительные возможности, благодаря которым можно реализовать более трудные задачи, чем обычно решаются контроллером страниц. Я не буду вдаваться в подробности реализации контроллера страниц, а скажу лишь, что в практической части будет разработан именно контроллер запросов (некоторое подобие).
1.2. Маршрутизация URL
Маршрутизация URL позволяет настроить приложение на прием запросов с URL, которые не соответствуют реальным файлам приложения, а также использовать ЧПУ , которые семантически значимы для пользователей и предпочтительны для поисковой оптимизации.
К примеру, для обычной страницы, отображающей форму обратной связи, URL мог бы выглядеть так: http://www.example.com/contacts.php?action=feedback
Приблизительный код обработки в таком случае: switch
($_GET
["action"
])
{
case
"about"
:
require_once
("about.php"
); // страница "О Нас"
break
;
case
"contacts"
:
require_once
("contacts.php"
); // страница "Контакты"
break
;
case
"feedback"
:
require_once
("feedback.php"
); // страница "Обратная связь"
break
;
default
:
require_once
("page404.php"
); // страница "404"
break
;
}
Думаю, почти все так раньше делали.
С использованием движка маршрутизации URL вы сможете для отображения той же информации настроить приложение на прием таких запросов: http://www.example.com/contacts/feedback
Здесь contacts представляет собой контроллер, а feedback — это метод контроллера contacts, отображающий форму обратной связи и т.д. Мы еще вернемся к этому вопросу в практической части.
Также стоит знать, что маршрутизаторы многих веб-фреймворков позволяют создавать произвольные маршруты URL (указать, что означает каждая часть URL) и правила их обработки. Теперь мы обладаем достаточными теоретическими знаниями, чтобы перейти к практике.
2. Практика
Для начала создадим следующую структуру файлов и папок:
Забегая вперед, скажу, что в папке core будут храниться базовые классы Model, View и Controller. Их потомки будут храниться в директориях controllers, models и views. Файл index.php
это точка в хода в приложение. Файлbootstrap.php
инициирует загрузку приложения, подключая все необходимые модули и пр.
Будем идти последовательно; откроем файл index.php и наполним его следующим кодом: ini_set("display_errors"
, 1
);
require_once
"application/bootstrap.php"
;
Тут вопросов возникнуть не должно.
Следом, сразу же перейдем к фалу bootstrap.php
: require_once
"core/model.php"
;
require_once
"core/view.php"
;
require_once
"core/controller.php"
;
require_once
"core/route.php"
;
Route::start(); // запускаем маршрутизатор
Первые три строки будут подключать пока что несуществующие файлы ядра. Последние строки подключают файл с классом маршрутизатора и запускают его на выполнение вызовом статического метода start.
2.1. Реализация маршрутизатора URL
Пока что отклонимся от реализации паттерна MVC и займемся мрашрутизацией. Первый шаг, который нам нужно сделать, записать следующий код в .htaccess
: RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
Этот код перенаправит обработку всех страниц на index.php
, что нам и нужно. Помните в первой части мы говорили о Front Controller?!
Маршрутизацию мы поместим в отдельный файлroute.php
в директорию core. В этом файле опишем класс Route, который будет запускать методы контроллеров, которые в свою очередь будут генерировать вид страниц.
Содержимое файла route.php
class
Route
{
static
function
start
()
{
// контроллер и действие по умолчанию
$controller_name
= "Main"
;
$action_name
= "index"
;
$routes
= explode("/"
, $_SERVER
["REQUEST_URI"
]);
// получаем имя контроллера
if
(!empty
($routes
))
{
$controller_name
= $routes
;
}
// получаем имя экшена
if
(!empty
($routes
))
{
$action_name
= $routes
;
}
// добавляем префиксы
$model_name
= "Model_"
.$controller_name
;
$controller_name
= "Controller_"
.$controller_name
;
$action_name
= "action_"
.$action_name
;
// подцепляем файл с классом модели (файла модели может и не быть)
$model_file
= strtolower($model_name
).".php"
;
$model_path
= "application/models/"
.$model_file
;
if
(file_exists($model_path
))
{
include
"application/models/"
.$model_file
;
}
// подцепляем файл с классом контроллера
$controller_file
= strtolower($controller_name
).".php"
;
$controller_path
= "application/controllers/"
.$controller_file
;
if
(file_exists($controller_path
))
{
include
"application/controllers/"
.$controller_file
;
}
else
{
/*
правильно было бы кинуть здесь исключение,
но для упрощения сразу сделаем редирект на страницу 404
*/
Route::ErrorPage404();
}
// создаем контроллер
$controller
= new
$controller_name
;
$action
= $action_name
;
if
(method_exists($controller
, $action
))
{
// вызываем действие контроллера
$controller
->$action
();
}
else
{
// здесь также разумнее было бы кинуть исключение
Route::ErrorPage404();
}
}
function
ErrorPage404
()
{
$host
= "http://"
.$_SERVER
["HTTP_HOST"
]."/"
;
header("HTTP/1.1 404 Not Found"
);
header("Status: 404 Not Found"
);
header("Location:"
.$host
."404"
);
}
}
Замечу, что в классе реализована очень упрощенная логика (несмотря на объемный код) и возможно даже имеет проблемы безопасности. Это было сделано намерено, т.к. написание полноценного класса маршрутизации заслуживает как минимум отдельной статьи. Рассмотрим основные моменты…
В элементе глобального массива $_SERVER["REQUEST_URI"] содержится полный адрес по которому обратился пользователь. Например: example.ru/contacts/feedback
С помощью функции explode
производится разделение адреса на составлющие. В результате мы получаем имя контроллера, для приведенного примера, это контроллер contacts
и имя действия, в нашем случае — feedback
.
Далее подключается файл модели (модель может отсутствовать) и файл контроллера, если таковые имеются и наконец, создается экземпляр контроллера и вызывается действие, опять же, если оно было описано в классе контроллера.
Таким образом, при переходе, к примеру, по адресу: example.com/portfolio или example.com/portfolio/index роутер выполнит следующие действия:
подключит файл model_portfolio.php из папки models, содержащий класс Model_Portfolio;
подключит файл controller_portfolio.php из папки controllers, содержащий класс Controller_Portfolio;
создаст экземпляр класса Controller_Portfolio и вызовет действие по умолчанию — action_index, описанное в нем.
Если пользователь попытается обратиться по адресу несуществующего контроллера, к примеру: example.com/ufo то его перебросит на страницу «404»: example.com/404 То же самое произойдет если пользователь обратится к действию, которое не описано в контроллере.
2.2. Возвращаемся к реализации MVC
Перейдем в папку core и добавим к файлу route.php еще три файла: model.php, view.php и controller.php
Напомню, что они будут содержать базовые классы, к написанию которых мы сейчас и приступим.
Содержимое файла model.php
class
Model
{
public
function
get_data
()
{
}
}
Класс модели содержит единственный пустой метод выборки данных, который будет перекрываться в классах потомках. Когда мы будем создавать классы потомки все станет понятней.
Содержимое файла view.php
class
View
{
//public $template_view; // здесь можно указать общий вид по умолчанию.
function
generate
($content_view
, $template_view
, $data
= null)
{
/*
if(is_array($data)) {
// преобразуем элементы массива в переменные
extract($data);
}
*/
include
"application/views/"
.$template_view
;
}
}
Не трудно догадаться, что метод generate
предназначен для формирования вида. В него передаются следующие параметры:
$content_file — виды отображающие контент страниц;
$template_file — общий для всех страниц шаблон;
$data — массив, содержащий элементы контента страницы. Обычно заполняется в модели.
Функцией include динамически подключается общий шаблон (вид), внутри которого будет встраиваться вид для отображения контента конкретной страницы.
В нашем случае общий шаблон будет содержать header, menu, sidebar и footer, а контент страниц будет содержаться в отдельном виде. Опять же это сделано для упрощения.
Содержимое файла controller.php
class
Controller
{
public
$model
;
public
$view
;
function
__construct
()
{
$this
->view = new
View();
}
}
}
Метод action_index
— это действие, вызываемое по умолчанию, его мы перекроем при реализации классов потомков.
2.3. Реализация классов потомков Model и Controller, создание View"s
Теперь начинается самое интересное! Наш сайт-визитка будет состоять из следущих страниц:
Главная
Услуги
Портфолио
Контакты
А также — страница «404»
Для каждой из страниц имеется свой контроллер из папки controllers и вид из папки views. Некоторые страницы могут использовать модель или модели из папки models.
На предыдущем рисунке отдельно выделен файл template_view.php
— это шаблон, содержащий общую для всех страниц разметку. В простейшем случае он мог бы выглядеть так:
<html
lang
="ru"
>
<head
>
<meta
charset
="utf-
8
">
<title
>
Главнаяtitle
>
head
>
<body
>
$content_view
; ?>
body
>
html
>
Для придания сайту презентабельного вида сверстаем CSS шаблон и интегририруем его в наш сайт путем изменения структуры HTML-разметки и подключения CSS и JavaScript файлов: <link
rel
="stylesheet"
type
="text/css"
href
="/css/style.css"
/>
<script
src
="/js/jquery-1.6.2.js"
type
="text/javascript"
>
script
>
В конце статьи, в разделе «Результат», приводится ссылка на GitHub-репозиторий с проектом, в котором проделаны действия по интеграции простенького шаблона.
2.3.1. Создадаем главную страницу
Начнем с контроллера controller_main.php
, вот его код: class
Controller_Main
extends
Controller
{
function
action_index
()
{
$this
->view->generate("main_view.php"
, "template_view.php"
);
}
}
В метод generate
экземпляра класса View передаются имена файлов общего шаблона и вида c контентом страницы. Помимо индексного действия в контроллере конечно же могут содержаться и другие действия.
Файл с общим видом мы рассмотрели ранее. Рассмотрим файл контента main_view.php
: <h1
>
Добро пожаловать!h1
>
<p
>
<img
src
="/images/office-small.jpg"
align
="left"
>
<a
href
="/"
>
ОЛОЛОША TEAMa
>
- команда первоклассных специалистов в области разработки веб-сайтов с многолетним опытом коллекционирования мексиканских масок, бронзовых и каменных статуй из Индии и Цейлона, барельефов и изваяний, созданных мастерами Экваториальной Африки пять-шесть веков назад...
p
>
Здесь содержиться простая разметка без каких либо PHP-вызовов. Для отображения главной странички можно воспользоваться одним из следующих адресов:
методы библиотек, реализующих абстракицю данных. Например, методы библиотеки PEAR MDB2;
методы ORM;
методы для работы с NoSQL;
и др.
Для простоты, здесь мы не будем использовать SQL-запросы или ORM-операторы. Вместо этого мы сэмулируем реальные данные и сразу возвратим массив результатов. Файл модели model_portfolio.php
поместим в папку models. Вот его содержимое: class
Model_Portfolio
extends
Model
{
public
function
get_data
()
{
return
array
(array
("Year"
=> "2012"
,
"Site"
=> "http://DunkelBeer.ru"
,
"Description"
=> "Промо-сайт темного пива Dunkel от немецкого производителя Löwenbraü выпускаемого в России пивоваренной компанией "CАН ИнБев"."
),
array
("Year"
=> "2012"
,
"Site"
=> "http://ZopoMobile.ru"
,
"Description"
=> "Русскоязычный каталог китайских телефонов компании Zopo на базе Android OS и аксессуаров к ним."
),
// todo
);
}
}
Класс контроллера модели содержится в файле controller_portfolio.php
, вот его код: class
Controller_Portfolio
extends
Controller
{
function
__construct
()
{
$this
->model = new
Model_Portfolio();
$this
->view = new
View();
}
function
action_index
()
{
$data
= $this
->model->get_data();
$this
->view->generate("portfolio_view.php"
, "template_view.php"
, $data
);
}
}
В переменную data
записывается массив, возвращаемый методом get_data
, который мы рассматривали ранее. Далее эта переменная передается в качестве параметра метода generate
, в который также передаются: имя файла с общим шаблон и имя файла, содержащего вид c контентом страницы.
Вид содержащий контент страницы находится в файле portfolio_view.php
.
Портфолио
Все проекты в следующей таблице являются вымышленными, поэтому даже не пытайтесь перейти по приведенным ссылкам.
Год
Проект
Описание
"
.$row
["Year"
]."
"
.$row
["Site"
]."
"
.$row
["Description"
]."
"
;
}
Ссылка на GitHub: https://github.com/vitalyswipe/tinymvc/zipball/v0.1
А вот в этой версии я набросал следующие классы (и соответствующие им виды):
Controller_Login в котором генерируется вид с формой для ввода логина и пароля, после заполнения которой производится процедура аутентификации и в случае успеха пользователь перенаправляется в админку.
Contorller_Admin с индексным действием, в котором проверяется был ли пользователь ранее авторизован на сайте как администратор (если был, то отображается вид админки) и действием logout для разлогинивания.
Аутентификация и авторизация — это другая тема, поэтому здесь она не рассматривается, а лишь приводится ссылка указанная выше, чтобы было от чего оттолкнуться.
4. Заключение
Шаблон MVC используется в качестве архитектурной основы во многих фреймворках и CMS, которые создавались для того, чтобы иметь возможность разрабатывать качественно более сложные решения за более короткий срок. Это стало возможным благодаря повышению уровня абстракции, поскольку есть предел сложности конструкций, которыми может оперировать человеческий мозг.
Но, использование веб-фреймворков, типа Yii или Kohana, состоящих из нескольких сотен файлов, при разработке простых веб-приложений (например, сайтов-визиткок) не всегда целесообразно. Теперь мы умеем создавать красивую MVC модель, чтобы не перемешивать Php, Html, CSS и JavaScript код в одном файле.
Данная статья является скорее отправной точкой для изучения CMF, чем примером чего-то истинно правильного, что можно взять за основу своего веб-приложения. Возможно она даже вдохновила Вас и вы уже подумываете написать свой микрофреймворк или CMS, основанные на MVC. Но, прежде чем изобретать очередной велосипед с «блекджеком и шлюхами», еще раз подумайте, может ваши усилия разумнее направить на развитие и в помощь сообществу уже существующего проекта?!
P.S.: Статья была переписана с учетом некоторых замечаний, оставленных в комментариях. Критика оказалась очень полезной. Судя по отклику: комментариям, обращениям в личку и количеству юзеров добавивших пост в избранное затея написать этот пост оказалось не такой уж плохой. К сожалению, не возможно учесть все пожелания и написать больше и подробнее по причине нехватки времени… но возможно это сделают те таинственные личности, кто минусовал первоначальный вариант. Удачи в проектах!
5. Подборка полезных ссылок по сабжу
В статье очень часто затрагивается тема веб-фреймворков — это очень обширная тема, потому что даже микрофреймворки состоят из многих компонентов хитро увязанных между собой и потребовалась бы не одна статья, чтобы рассказать об этих компонентах. Тем не менее, я решил привести здесь небольшую подборку ссылок (по которым я ходил при написаниие этой статьи), которые так или иначе касаются темы фреймворков.
This example demonstrates how to automatically logout with default Spring security configuration.
To logout, we just need to access URL "/logout" with POST request.
In the POST /logout form, we also need to include the CSRF token, which is a protection against CSRF attack .
Note that, in above configuration, we are also overriding configure(HttpSecurity http) to omit the default Basic Authentication (see the original method in WebSecurityConfigurerAdapter source code) and use form based Authentication. We are doing so because browsers cache the Basic Authentication information aggressively (after the first successful login) and there is no way to logout the user in the current session. In most of the examples, we will not be using Basic Authentication mechanism.
A controller
@Controller
public class ExampleController {
@RequestMapping("/")
public String handleRequest2(ModelMap map) {
map.addAttribute("time", LocalDateTime.now().toString());
return "my-page";
}
}
The JSP page
src/main/webapp/WEB-INF/views/my-page.jsp
Spring Security Example
Time: ${time}
To try examples, run embedded tomcat (configured in pom.xml of example project below):
Mvn tomcat7:run-war
Output
Initial access to URI "/" will redirect to "/login":
After submitting user name and password as we setup in our AppConfig class:
Мы заккоментировали шаблон URL-адреса для представления user_login
, созданного ранее для использования представления login
Джанго.
Создайте новый каталог в каталоге шаблонов приложения account
и назовите его registration.
Создайте новый файл в новом каталоге, назовите его login.html
Your username and password didn"t match.
Please try again.
{% else %}
Please, use the following form to log-in:
{% endif %}
{% endblock %}
Этот шаблон для входа очень похож на созданный ранее. Джанго использует AuthenticationForm
, расположенную в django.contrib.auth.forms
. Эта форма пытается проверить подлинность пользователя и порождает ошибку проверки, если имя пользователя было не верно. В этом случае мы можем искать ошибки с помощью команды {% if form.errors %} . Обратите внимание, что мы добавили скрытый элемент для отправки значения переменной с именем next
.
Параметр next
должен быть URL-адресом. Если этот параметр указан, то после входа пользователя в систему он перенаправляется на заданный URL-адрес.
Теперь создайте шаблон logged_out.html
внутри каталога шаблона registration
и вставьте в него следующий код:
You have been successfully logged out. You can log-in again.
{% endblock %}
Это шаблон, который будет отображаться после входа пользователя в систему.
После добавления шаблонов URL-адресов и шаблонов для входных и выходных представлений сайт готов к входу в систему с использованием представлений аутентификации Джанго.
Обратите внимание, что представление logout_then_login
, включенное в наш urlconf
, не нуждается в шаблоне, поскольку он выполняет перенаправление на log in view
.
Теперь создадим новый view для отображения панели мониторинга для пользователя, чтобы знать когда пользователь войдет в свою учетную запись. Откройте файл views.py
приложения account
и добавьте в него следующий код:
Мы добавляем в наше представление декоратор login_required
authentication framework. Декоратор login_required
проверяет, прошел ли текущий пользователь аутентификацию. Если пользователь прошел аутентификацию, рпедставление выполнится; Если пользователь не прошел аутентификацию, он будет перенаправлян на страницу входа.
Мы также определили переменную section
. Мы собираемся использовать эту переменную для отслеживания того раздела сайта, за которым наблюдает пользователь.
Теперь необходимо создать шаблон для представления панели мониторинга. Создайте новый файл внутри шаблонов/учетной templates/account/
и назовите его dashboard.html
:
LOGIN_REDIRECT_URL
: Сообщает о том, на какой URL-адрес перенаправлять пользователя после входа в систему.
LOGIN_URL
: URL-адрес для перенаправления пользователя на вход (например, с помощью декоратора login_required
)
LOGOUT_URL
: URL-адрес для перенаправления пользователя на выход
Теперь мы собираемся добавить к нашему базовому шаблону ссылки на вход и выход с сайта.
Для этого необходимо определить, вошел ли текущий пользователь в систему или нет, чтобы отобразить соответствующую текущему состоянию пользователя, ссылку. Текущий пользователь задается в HttpRequest
объекте промежуточного класса authentication. Доступ к нему можно получить с помощью request.user
. В запросе будет найден объект user, даже если user не прошел аутентификацию. Неаутентифицированный пользователь, задается в запросе в качестве экземпляра AnonymousUser
. Наилучший способ проверки состояния аутентификаци текущего пользователя — вызов request.user.is_authenticated()
Как можно видеть, меню сайта отображается только для пользователей, прошедших аутентификации. Мы также проверяем текущий раздел, чтобы добавить выбранный атрибут класса к соответствующему элементу
, чтобы выделить текущий раздел в меню с помощью CSS. Также отображается имя пользователя и ссылка для выхода в систему, если пользователь прошел аутентификацию, или ссылка для входа в систему.
Откройте в браузере http://127.0.0.1:8000/account/login/ . Вы должны увидеть стриницу входа. Введите валидный логин и пароль. Вы увидите следующее:
Можно увидеть, что раздел My dashboard выделен с помощью CSS, так как он имеет class selected
. Поскольку пользователь прошел аутентификацию, имя пользователя отображается в правой части header-а. Щелкните ссылку Logout
. Вы увидите следующую страницу:
На этой странице можно увидеть, что пользователь вышел из системы, и поэтому больше не отображается меню веб-сайта. Ссылка в правой стороне хедера показывает теперь Log-in
.
Если вы видите страницу log out из сайта администрирования Джанго, а не собственную страницу выхода из системы, проверьте настройки INSTALLED_APPS и убедитесь, что django.contrib.admin
находится после account
. Оба шаблона находятся в том же относительном пути, и загрузчик шаблона Джанго будет использовать первый найденный.