Файл: Практикум для студентов, обучающихся по направлению подготовки 09. 03. 04 Программная инженерия.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 30.11.2023

Просмотров: 173

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Класс, наследующийся от WebSecurityConfigurerAdapter, является фактически входной точкой со всей конфигурацией. Для начала запретим все эндпоинты, кроме /login, /logout для неавторизованных пользователей, а также отключим Cross Origin Resource Sharing (CORS) и Cross Site Request Forgery
(CSRF). Они сейчас не имеют значение, но могут усложнить изучение Spring
Security:
@Configuration public class SecurityConfig extends
WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) throws
Exception { http.csrf().disable().cors().disable()
.authorizeRequests().antMatchers("/login",
"/logout").permitAll()
.anyRequest().authenticated();
}
}
Теперь хотелось бы добавить форму логина, а также какой-то источник логинов и паролей пользователей:
@Configuration public class SecurityConfig extends
WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) throws
Exception { http.csrf().disable().cors().disable()
.authorizeRequests().antMatchers("/login",
"/logout").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.and().userDetailsService(userDetailsService());
}
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsService = new
InMemoryUserDetailsManager(); userDetailsService.createUser(new
User("user",
"password", List.of(new SimpleGrantedAuthority("ROLE_USER")))); return userDetailsService;
}
@Bean
PasswordEncoder encoder() { return NoOpPasswordEncoder.getInstance();
}
}
PasswordEncoder – класс, который отвечает за кодирование паролей. В данном случае используется NoOpPasswordEncoder, но никогда его не стоит использовать в реальном проекте – он никак не шифрует пароли. В данном случае он используется просто для простоты. А теперь запустим проект и попробуем перейти на защищенный эндпоинт. Нас отправит на /login
(рисунок 36).
Рисунок 36 – Форма авторизации
Попробуем ввести наш логин «user» и пароль «password». После логина перейдем на защищенный эндпоинт, и увидим информацию.

Также нам хотелось бы еще где-то хранить сессию. Для этого используется Spring Session, который активируется добавлением одной зависимости – spring session jdbc.
23.2. Задание
В приложении из предыдущего задания добавить возможность регистрации и авторизации пользователей, хранение cookie сессий в базе данных PostgreSQL, хеширование паролей алгоритмом Bcrypt, защиту всех запросов, кроме запросов на авторизацию и регистрацию, от неавторизированных пользователей.

24. ПРАКТИЧЕСКАЯ РАБОТА № 24
Цель работы
Тестирование в Spring Framework с использованием Junit.
24.1. Теоретическая часть
В данном задании мы обратим внимание на модульное тестирование – такой вид тестирования, в котором тестируется отдельный модуль, класс, в изоляции от остальных, на правильное функционирование. Модульное тестирование важно не на стадии создания данных тестов, а при дальнейшем развитии кодовой базы, когда тесты не дадут сломаться тому, что уже работает. Для написания модульных тестов будем использовать библиотеку
JUnit, которая тоже прекрасно интегрирована с Spring.
Также нам потребуется создание mock объектов – реализаций некоторых объектов-пустышек, не выполняющих логики, либо симулирующие выполнение какой-то логики. Также мы можем определять, что они будут возвращать, для удобства тестирования. Мы будем тестировать
UserService из предыдущего задания.
Для начала создадим класс в папке test UserServiceImplTest, и добавим два метода – getUsers, saveOrUpdate, и пометим аннотацией Test. class UserServiceImplTest {
@Test void getUsers() {
}
@Test void saveOrUpdate() {
}
}
Уже сейчас мы можем запустить, и тесты успешно пройдут. Но нам нужно все же проверить какую-то логику. Но для начала нам нужно сделать mock объект интерфейса UserRepository. Для этого добавим аннотацию


ExtendWith для активации Mockito, а также добавим свойство UserRepository с аннотацией Mock:
@ExtendWith(MockitoExtension.class) class UserServiceImplTest {
@Mock private UserRepository userRepository;
@Test void getUsers() {
}
@Test void saveOrUpdate() {
}
}
Теперь уже добавим логику в тест getUsers:
@ExtendWith(MockitoExtension.class) class UserServiceImplTest {
@Mock private UserRepository userRepository;
@Test void getUsers() {
User user = new User(); user.setFirstName("Vasya");
User user2 = new User(); user2.setFirstName("Dima");
Mockito.when(userRepository.findAll()).thenReturn(List.of(user, user2));
UserService userService = new
UserServiceImpl(userRepository);
Assertions.assertEquals(2, userService.getUsers().size());
Assertions.assertEquals("Vasya", userService.getUsers().get(0).getFirstName());
}
@Test void saveOrUpdate() {

}
}
Assertions отвечает за проверку данных – являются ли они теми, которые мы ожидаем от программы, или нет. Теперь добавим логику для метода saveOrUpdate:
@ExtendWith(MockitoExtension.class) class UserServiceImplTest {
@Mock private UserRepository userRepository;
@Captor
ArgumentCaptor captor;
@Test void getUsers() {
User user = new User(); user.setFirstName("Vasya");
User user2 = new User(); user2.setFirstName("Dima");
Mockito.when(userRepository.findAll()).thenReturn(List.of(user, user2));
UserService userService = new
UserServiceImpl(userRepository);
Assertions.assertEquals(2, userService.getUsers().size());
Assertions.assertEquals("Vasya", userService.getUsers().get(0).getFirstName());
}
@Test void saveOrUpdate() {
User user = new User(); user.setFirstName("Vitya");
UserService userService = new
UserServiceImpl(userRepository); userService.saveOrUpdate(user);
Mockito.verify(userRepository).save(captor.capture());
User captured = captor.getValue();
assertEquals("Vitya", captured.getFirstName());
}
}
ArgumentCaptror отвечает за перехват аргументов. Нам нужно узнать, поменялся ли как-то объект User в процессе выполнения метода UserService, поэтому нам нужно перехватить аргумент и проверить его.
Тестирование также важно, как и сама разработка, ведь любой код в первую очередь пишется для того, чтобы его кто-то использовал – как приложение, как библиотеку, не важно. Код всегда должен выполнять бизнес- требования, иначе и само программирование становится бесполезным.
24.2. Задание
Написать модульное тестирование для всех классов сервисов приложения из предыдущего задания.

25. ОПИСАНИЕ ВЫПОЛНЕНИЯ РАБОТ
25.1. Последовательность выполнения практической работы
Для выполнения практических работ необходимо:
1) на рабочем месте, где будут выполняться практические работы, установить следующие средства разработки: а) OpenJDK версии 11 и выше; б) InteliJ IDEA Community Edition (желательно Ultimate Edition, можно получить по студенческой лицензии на сайте Jetbrains); в) Docker;
2) создать пустой проект в InteliJ IDEA;
3) создать пустой класс, содержащий статический main метод;
4) запустить созданную программу и убедиться в работоспособности.
25.2. Порядок выполнения индивидуального задания
Индивидуальное задание должно быть оформлено в отдельном проекте.
Для проверки работоспособности выполненного индивидуального задания следует использовать отдельный класс с методом main.


26. ЗАЩИТА ПРАКТИЧЕСКИХ РАБОТ
26.1. Результат практической работы
Результатом практической работы является:
1) рабочий проект, выполненный в соответствии с заданием практической работы;
2) отчет, содержащий все этапы выполненной работы, оформленный по примеру.
26.2. Этапы защиты практической работы
Этапы защиты практической работы:
1) демонстрация рабочего проекта, выполненного в соответствии с заданием;
2) ответы на дополнительные вопросы по рабочему проекту (студент должен владеть теоретической базой, свободно читать и комментировать строки листинга программы, уметь формулировать выводы о проделанной работе);
3) отчет по практической работе предоставляется в электронном виде.

ПЕРЕЧЕНЬ СОКРАЩЕНИЙ
AOP
– Aspect Oriented Programming

API

Application programming Interface

CORS –
Cross Origin Resource Sharing

CSRF –
Cross Site Request Forgery

DI

Dependency Injection

DSL

Domain specific language

DTO

Data Transfer Object

HQL

Hibernate Query Language

HTTP –
HyperText Transfer Protocol

IoC

Inversion of Control

JDK

Java Development Kit

JMX

Java Management Extensions

JPA

Java Persistence API

JVM

Java Virtual Machine

MVC –
Model-View-Controller

ORM –
Object Relational Mapping

SQL

Structured query language

xml

eXtensible Markup Language

БД

база данных


БИБЛИОГРАФИЧЕСКИЙ СПИСОК
1. Стелтинг С., Маасен О. Применение шаблонов Java. Библиотека профессионала.: Пер. с англ. — М.: Издательский дом "Вильяме", 2002. —
576 с.: ил. — Парал. тит. англ.
2. Functional Interfaces in Java: Fundamentals and Examples 1st ed. Edition,
Kindle
Edition
[Электронный ресурс].
URL: https://www.amazon.com/Functional-Interfaces-Java-Fundamentals-Examples- ebook/dp/B07NRHQSCW (дата обращения: 29.01.21). Заголовок с экрана.
3. Hibernate Search 6.0.0.Final: Reference Documentation [Электронный ресурс].
URL: https://docs.jboss.org/hibernate/stable/search/reference/en-
US/html_single/ (дата обращения: 29.01.21). Заголовок с экрана.
4. Паттерны проектирования на Java. Каталог Java-примеров.
[Электронный ресурс]. URL: https://refactoring.guru/ru/design-patterns/java
(дата обращения: 29.01.21). Заголовок с экрана.
5. Руководство по
Spring
[Электронный ресурс].
URL: https://proselyte.net/tutorials/spring-tutorial-full-version/
(дата обращения:
29.01.21). Заголовок с экрана.
6. The
Reactive
Manifesto
[Электронный ресурс].
URL:
https://www.reactivemanifesto.org/ (дата обращения: 29.01.21). Заголовок с экрана.
7. Spring Framework Documentation [Электронный ресурс]. URL: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html
(дата обращения: 29.01.21). Заголовок с экрана.
8. Hibernate Search 6.0.0. Final: Reference Documentation [Электронный ресурс].
URL: https://docs.jboss.org/hibernate/stable/search/reference/en-
US/html_single/ (дата обращения: 29.01.21). Заголовок с экрана.