Быстрый старт в Spring Security – Devcolibri

Шаг 2. начинаем с конца, делаем внешний вид

Для большей привлекательности как к внешнему виду, так и мотивации изучить этот урок, я решил использовать Bootstrap 3.

Скачиваем bootstrap и в проекте создаем папку webapp/pages/ и копируем туда файлы bootstrap-а. (смотрите на структуре проекта)

Теперь создаем webapp/pages/index.jsp:

Making the home page public

There’s one final change you’ll need to make.

This app will now work fine and authenticate as before, but it’s still going to redirect before showing the page. To make the link visible, we also need to switch off the security on the home page by extending WebSecurityConfigurerAdapter:

Spring Boot attaches special meaning to a WebSecurityConfigurerAdapter on the class annotated with @SpringBootApplication: It uses it to configure the security filter chain that carries the OAuth 2.0 authentication processor.

The above configuration indicates a whitelist of permitted endpoints, with every other endpoint requiring authentication.

You want to allow:

Используемые технологии

Это будет очень простое веб приложение, Hello World на базе Spring MVC и Spring Security. Все настройки мы осуществим используя только Java классы, без единой строчки конфигурации в XML.

Начнем с рассмотрения структуры проекта.

Исходный код


Полный исходный код рассмотренного приложения находится на Github.

Настраиваем spring mvc (webconfig.java)

Необходимо указать фреймворку Spring где находятся компоненты представления, и как их отображать. Так же надо привязать настройки безопасности. Все это можно сделать с помощью Java класса с аннотацией

@Configuration

(в будущем мы будем называть такие классы конфигурационными).

WebConfig.java

package com.elennaro.sshwa.config.application;

//Import section ommited...

@Configuration
@EnableWebMvc
@ComponentScan({ "com.elennaro.sshwa.config", "com.elennaro.sshwa.controllers" })
//@Import({ AppSecurityConfig.class })
public class WebConfig {
 
@Bean
 public InternalResourceViewResolver viewResolver() {
 InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
 viewResolver.setViewClass(JstlView.class);
 viewResolver.setPrefix("/WEB-INF/views/");
 viewResolver.setSuffix(".jsp");
 return viewResolver;
 }
}

Коротко рассмотрим код приведенный выше:

Далее рассмотрим непосредственно настройки безопасности Spring Security.

Настроим spring security.

Соберем все проделанное выше вместе и настроим Spring Security.

Немного теории

Аутентификация

Переопределим authenticationfailurehandler.


В случае, если пользователь не прошел аутентификацию, мы перенаправим его по адресу обратного вызова, который был передан в начале процесса аутентификации с параметром error, содержащим текст ошибки.

ExampleAuthenticationFailureHandler

public class ExampleAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    private final HttpCookieOAuth2AuthorizationRequestRepository authorizationRequestRepository;

    public ExampleAuthenticationFailureHandler(
            HttpCookieOAuth2AuthorizationRequestRepository authorizationRequestRepository) {
        this.authorizationRequestRepository = requireNonNull(authorizationRequestRepository);
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        String targetUrl = getFailureUrl(request, exception);
        authorizationRequestRepository.removeAuthorizationRequestCookies(request, response);
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    private String getFailureUrl(HttpServletRequest request, AuthenticationException exception) {
        String targetUrl = getCookie(request, Cookies.REDIRECT_URI)
                .map(Cookie::getValue)
                .orElse(("/"));

        return UriComponentsBuilder.fromUriString(targetUrl)
                .queryParam("error", exception.getLocalizedMessage())
                .build().toUriString();
    }
}

Перечисление url

Итак:

Подготовка

В прошлом примере мы настроили аутентификацию типа In-Memory, при которой пользователи хранятся в памяти приложения. Пример простой и подходящий для демонстрации настройки авторизации.

Пользователи (in-memory athentication)

А настройка аутентификации (см. предыдущий пример) выглядит теперь так:

Представления (вьюшки)

helloworld.jsp

Реализация

Мы реализуем REST-сервис, предоставляющий следующее API:

  • GET /auth/login — запустить процесс аутентификации пользователя.
  • POST /auth/token — запросить новую пару access/refresh токенов.
  • GET /api/repositories — получить список Bitbucket репозиториев текущего пользователя.

Быстрый старт в Spring Security – Devcolibri

Высокоуровневая архитектура приложения.

Заметим, что поскольку приложение состоит из трех взаимодействующих компонентов, помимо того, что мы выполняем авторизацию запросов клиента к серверу, Bitbucket авторизует запросы сервера к нему. Мы не будем настраивать авторизацию методов по ролям, чтобы не делать пример сложнее. У нас есть только один API метод GET /api/repositories, вызывать который могут только аутентифицированные пользователи. Сервер может выполнять на Bitbucket любые операции, разрешенные при регистрации OAuth клиента.
Быстрый старт в Spring Security – Devcolibri
Процесс регистрации OAuth клиента описан в предыдущей статье.

Для реализации мы будем использовать Spring Boot версии 2.2.2.RELEASE и Spring Security версии 5.2.1.RELEASE.

Создадим tokenauthenticationfilter.

Задача этого фильтра извлечь токен доступа из заголовка Authorization в случае его наличия, провалидировать его и инициализировать секьюрити контекст.

Ссылки

  • OAuth — Википедия
  • Spring Security Reference
  • JSON Web Token (JWT)
  • The OAuth 2.0 Authorization Framework

P.S.

Структура проекта.

Быстрый старт в Spring Security – Devcolibri

Финиш.

Запускаем Приложение:

Шаг 1. создание проекта и подключение зависимостей

Начнем с традиционного создания проекта:

Создали Maven проект, теперь добавим зависимости в pom.xml их будет довольно таки много, поэтому прикладываю полный pom файл:

Шаг 10. регистрация конфигураций в контексте spring

Чтобы Spring видел наши конфигурации, а именно WebAppConfig и SecurityConfig их нужно зарегистрировать в контексте Spring.

Создаем в пакете config класс Initializer и реализуем WebApplicationInitializer:

package com.devcolibri.secure.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

public class Initializer implements WebApplicationInitializer {

    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        // регистрация конфигураций в Spring контексте
        ctx.register(WebAppConfig.class);
        ctx.register(SecurityConfig.class);
        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        Dynamic servlet = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}

На этом этап конфигурации проекта можно считать законченным.

B web.xml нужно добавить фильтр, который будет определять наши реквесты и проверять валидность сессии:

Шаг 11. развертывание и тестирование

Пора все собрать и развернуть на сервере приложений.

Собираем проект с помощью Maven:

Теперь развертываем собранный собранный war на сервере приложений, я выбрал Tomcat 8.

Конфигурируем Intellij IDEA под Tomcat. Заходим в Edit Configuration…

Нажимаем по плюсику (Add New Configuration…) ищем там Tomcat Server -> Local:

Конфигурируем также как показано на скриншоте, потом переходим в раздел Deployment:

Жмем Add -> External Source… в корне вашего проекта будет папка target в ней будет secure-exam.war выбираем его и в поле Application context пишем /secure.

Шаг 3. создаем контроллеры

О создании MVC проекта на Spring можно почитать урок Spring MVC Hello World

Создаем пакет controller и класс MainController:

package com.devcolibri.secure.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/")
public class MainController {

    @RequestMapping(method = RequestMethod.GET)
    public String start(Model model){
        return "index";
    }

}

Этот контроллер будет просто направлять пользователя на страницу index.jsp.

А теперь создадим второй аналогичный контроллер, который будет показывать пользователю страничку login.jsp.

Создаем класс и называем его LoginController:

package com.devcolibri.secure.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/login")
public class LoginController {

    @RequestMapping(method = RequestMethod.GET)
    public String loginPage(Model model){
        return "login";
    }

}

Теперь мы сможем ходить по страничкам.

Шаг 4. конфигурирование spring mvc

Теперь нам нужно сконфигурировать Spring MVC чтобы он имел возможность разворачивать свой контекс и мы могли получать доступ к нашим бинам.

Создаем в пакете config класс WebAppConfig и наследуем его от WebMvcConfigurerAdapter:

Шаг 5. создание entity

Так как цель урока показать пример использования Spring Security, то я не стал реализовывать работу с БД, а всего лишь создал все необходимое для этого, чтобы в будущем реализовать Spring DATA.

Шаг 6. создаем слой services

Обычно проекты имеют несколько уровней слоёв, о которых я еще напишу статью, но один из этих слоёв мы реализуем прям сейчас.

Шаг 9. конфигурирование spring security

Теперь самое главное, заставить все это заработать 🙂

Создаем в пакете config класс SecurityConfig и наследуем его от WebSecurityConfigurerAdapter:

Настраиваем диспетчер сервлета (webappinitializer.java)

WebAppInitializer.java

Настройки безопасности (spring security — appsecurityconfig.java, securityinit.java)

AppSecurityConfig.java

Итоги

Пример доступен на GitHub.

Также см.  тут как защитить конкретные методы с помощью @Preauthorize.

Создадим login endpoint.

Для аутентификации пользователя мы по-прежнему используем OAuth2 с типом авторизации Authorization Code. Однако на предыдущем шаге мы заменили стандартный AuthenticationEntryPoint своей реализацией, поэтому нам нужен явный способ запустить процесс аутентификации.

Создадим repositories endpoint.

То ради чего и нужна была аутентификация через OAuth2 и Bitbucket — возможность использовать Bitbucket API для доступа к своим ресурсам. Используем Bitbucket repositories API для получения списка репозиториев текущего пользователя.

Похожее:  «Не путайте пользователя»: 14 элементов и 10 правил для эффективной навигации по сайту | Rusbase

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *