Введение. Зачем я вообще это пишу?
Эта статья является первой, написанной мной. Буду очень рад, если она все же будет опубликована. На данный момент являюсь Junior Java разработчиком, поэтому в этой статье не будет сложной аналитики и глубокого погружения в тему, но я свой опыт изучения и реализации приложений с использованием Spring Security, возможно, кому-то это поможет справиться с теми трудностями, с которыми встретился я.
Недавно мне пришлось подключать и настраивать авторизацию через Spring Security версии 3.1.0. В процессе разработки и решения сложностей, которых было не мало, я заметил, что информации по версии 3.1.0 довольно м��ло, если не считать документацию. (https://docs.spring.io/spring-security/reference/index.html)
Настройки приложения
Первым делом, начав работу над добавлением авторизации в свое приложение, я добавил соответствующую зависимость в pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Следующий шагом я приступил к настройке базы данных и подключению PostgreSQL. Я решил использовать application.yml вместо application.properties, так как данный формат является более удобным и читаемым
spring: datasource: url: jdbc:postgresql://localhost:5432/demoproject username: postgres password: password!456 driver-class-name: org.postgresql.Driver
SecurityConfig
Основные сложности у меня возникли в конфигурации, поэтому попробую расписать подробнее.
Первым делом я создал объект DataSource, который позволил связать Security с
приложением.
private DataSource dataSource; @Autowired public SecurityConfig(DataSource dataSource) { this.dataSource = dataSource; }
Следующим шагом я реализовал метод, создающий сущность JdbcUserDetailsManager. JdbcUserDetailsManager - реализует интерфейс UserDetailsManager, который позволяет работать с пользователями, в том числе создавать их при необходимости. Так как цели реализовывать полноценный механизм регистрации нет, то воспользовался методом createUser().
@Bean public JdbcUserDetailsManager user(PasswordEncoder encoder) { UserDetails admin = User.builder() .username("admin") .password(encoder.encode("adm_psw")) .roles("ADMIN") .authorities("ADMIN") .build(); JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource); jdbcUserDetailsManager.createUser(admin); return jdbcUserDetailsManager; }
Момент создания пользователя можно исключить и реализовать возможность полноценной регистрации или иным образом заполнить базу необходимыми данными - дальнейшую работу с базой я стал вести с Liquibase. Тогда метод будет выглядеть так:
@Bean public JdbcUserDetailsManager user(PasswordEncoder encoder) { JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource); return jdbcUserDetailsManager; }
В базе так же должны быть таблицы authorities:
create table authorities ( username varchar, authority varchar );
и users:
create table users ( username varchar, password varchar, enabled varchar priority integer );
Далее логика доступа к необходимым эндпоинтам. Необходимый эндпоинт прописывается в requestMatchers(). С помощью hasAuthority или hasRole позволяем доступ определенной категории пользователей
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests( (authorize) -> authorize .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll() .requestMatchers("/admin").hasAuthority("ADMIN") .requestMatchers("/user").hasAuthority("USER") .anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()); return http.build(); }
Заключение
На этом в целом все. Далее можно создать тестовый контроллер и проверить работу авторизации в приложении. Как вариант, проверка через постман. Для этого в Authorization выбирает type Basic Auth. В полях username и password прописываем заданные ранее значения.
Подробную информацию о специфике методов и работы с Spring Security все же рекомендую брать из документации.
Код моего проекта можно найти на моем аккаунте в GitHub
Так же буду рад получить советы и рекомендации как по коду, так и по написанию статей.
