Java for Beginner
695 subscribers
605 photos
165 videos
12 files
938 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Настройка ролей и прав доступа в Spring Security

1. Основные концепции


Authentication (аутентификация): процесс проверки подлинности пользователя, т.е. кто он такой.
Authorization (авторизация): процесс проверки прав пользователя, т.е. что он может делать.
Principal: представляет текущего аутентифицированного пользователя.
GrantedAuthority: представляет разрешение или роль, назначенную пользователю.
Role: определенная категория, которая группирует определенные разрешения.


2. Архитектура и основные компоненты

SecurityContext и SecurityContextHolder: SecurityContext хранит данные о текущей аутентификации, включая Principal и GrantedAuthority. SecurityContextHolder — это контейнер, который обеспечивает доступ к текущему SecurityContext.
AuthenticationManager: основной интерфейс для выполнения аутентификации. Он принимает объект Authentication и возвращает аутентифицированный объект или выбрасывает исключение.
AccessDecisionManager: принимает решение о предоставлении или отклонении доступа к защищенному ресурсу на основе предоставленных прав.
FilterSecurityInterceptor: фильтр, который проверяет доступ к ресурсам на основе настроек безопасности.


3. Настройка ролей и прав доступа

Spring Security поддерживает настройку через Java-код (Java Config) и XML.

3.1 Подключение Spring Security
Добавьте зависимости в pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>


3.2 Создание конфигурационного класса
Конфигурация Spring Security осуществляется с помощью аннотации @EnableWebSecurity и наследования от класса WebSecurityConfigurerAdapter.

Пример базовой конфигурации:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") // Только для ADMIN
.antMatchers("/user/**").hasRole("USER") // Только для USER
.antMatchers("/public/**").permitAll() // Доступ для всех
.anyRequest().authenticated() // Все остальные запросы требуют аутентификации
.and()
.formLogin() // Включить форму логина
.and()
.logout().permitAll(); // Разрешить logout для всех
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password(passwordEncoder().encode("adminPass")).roles("ADMIN")
.and()
.withUser("user").password(passwordEncoder().encode("userPass")).roles("USER");
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}


4. Роли и права: тонкая настройка

Роли (ROLE_*) — это абстракция для группировки прав. Spring
Security требует, чтобы роли начинались с префикса ROLE_.

4.1 Настройка прав доступа через аннотации
Spring Security поддерживает аннотации для определения прав доступа на уровне методов.

Включение поддержки аннотаций:

В классе конфигурации добавьте @EnableGlobalMethodSecurity:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// Конфигурация как ранее
}


#Java #Training #Spring #Security #Security_Roles
👍1
Использование аннотаций в методах:
@Service
public class MyService {

@PreAuthorize("hasRole('ADMIN')")
public void adminOnlyMethod() {
// Только для ADMIN
}

@PreAuthorize("hasAuthority('PERMISSION_VIEW')")
public void specificPermissionMethod() {
// Проверка конкретного разрешения
}

@PostAuthorize("returnObject.owner == authentication.name")
public MyEntity getEntity() {
// Проверка после выполнения метода
}
}


4.2 Определение прав доступа (Authorities)
Вместо простого использования ролей можно настроить более тонкие права:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password(passwordEncoder().encode("adminPass")).authorities("ROLE_ADMIN", "PERMISSION_READ", "PERMISSION_WRITE")
.and()
.withUser("user").password(passwordEncoder().encode("userPass")).authorities("ROLE_USER", "PERMISSION_READ");
}


5. Настройка пользовательской аутентификации и хранения данных

В реальных приложениях данные о пользователях и ролях хранятся в базе данных.

5.1 Создание модели пользователя
@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String username;
private String password;
private boolean enabled;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;

// Геттеры и сеттеры
}


5.2 Создание модели роли
@Entity
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@ManyToMany(mappedBy = "roles")
private Set<User> users;

// Геттеры и сеттеры
}


5.3 Создание пользовательского UserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {

@Autowired
private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));

return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
mapRolesToAuthorities(user.getRoles())
);
}

private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles) {
return roles.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}


5.4 Использование кастомного сервиса в конфигурации
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}


6. Защита REST API

Если вы разрабатываете REST API, можно отключить CSRF и использовать статeless-сессию:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/user/**").hasRole("USER")
.antMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic(); // Для простоты базовая аутентификация
}


#Java #Training #Spring #Security #Security_Roles
👍1