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

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

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

Spring Security предлагает различные подходы для аутентификации пользователей. Каждый из них предназначен для конкретных случаев использования, начиная от классической формы логина до современных методов на основе токенов, таких как JWT и OAuth2.

1. Форма логина (Form-Based Authentication)


1.1 Описание
Форма логина — это один из самых популярных методов аутентификации для веб-приложений. Пользователь вводит имя пользователя и пароль на странице входа, которые отправляются на сервер для проверки.

1.2 Настройка
Шаги настройки:
Настройка страницы логина.
Конфигурация Spring Security для обработки формы.


Пример конфигурации:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated() // Все запросы требуют аутентификации
)
.formLogin(form -> form
.loginPage("/login") // Кастомная страница логина
.permitAll() // Разрешить доступ к странице логина
)
.logout(logout -> logout
.permitAll() // Разрешить выход
);

return http.build();
}
}


Шаблон страницы логина:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form th:action="@{/login}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" /><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" /><br>
<button type="submit">Login</button>
</form>
</body>
</html>


Нюансы:
По умолчанию Spring Security предоставляет стандартную страницу логина, если не указана кастомная.
Все данные передаются через HTTPS для обеспечения безопасности.


2. HTTP Basic Authentication

2.1 Описание
HTTP Basic Authentication — это простой метод аутентификации, при котором имя пользователя и пароль передаются в заголовке HTTP-запроса.

2.2 Настройка
Пример конфигурации:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.httpBasic(); // Включение HTTP Basic
return http.build();
}


Пример запроса:
GET /api/resource HTTP/1.1
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=


Нюансы:
Подходит для API, но не рекомендуется для публичных веб-приложений, так как чувствительные данные передаются в заголовках.
Необходимо использовать HTTPS для защиты данных.


3. Token-Based Authentication


3.1 Описание
Вместо хранения сессий на сервере, токены используются для аутентификации. Самый популярный вариант — JWT (JSON Web Token).

3.2 Настройка JWT Authentication
1. Генерация токена:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import java.security.Key;
import java.util.Date;

@Service
public class JwtService {
private final String secretKey = "mysecretkeymysecretkeymysecretkeymysecretkey"; // 256 бит
private final long expirationMs = 86400000; // 1 день

public String generateToken(String username) {
Key key = Keys.hmacShaKeyFor(secretKey.getBytes());
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expirationMs))
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}
}


#Java #Training #Spring #Security #Security_Authority
2. JWT фильтр для валидации токенов:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Key;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final String secretKey = "mysecretkeymysecretkeymysecretkeymysecretkey";

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
Key key = Keys.hmacShaKeyFor(secretKey.getBytes());
String username = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();

if (username != null) {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(username, null, null));
}
}
filterChain.doFilter(request, response);
}
}


3. Регистрация фильтра:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}


Нюансы:
JWT-токены не требуют хранения на сервере.
Важно правильно настроить срок действия токена и защиту от кражи.


#Java #Training #Spring #Security #Security_Authority
4. OAuth2 Authentication

4.1 Описание
OAuth2 — это стандарт аутентификации, который позволяет пользователям аутентифицироваться с помощью сторонних сервисов, таких как Google, Facebook и т.д.

4.2 Настройка
Spring Security поддерживает OAuth2 через spring-boot-starter-oauth2-client.

Добавление зависимости:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>


Пример конфигурации:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.oauth2Login(oauth -> oauth
.loginPage("/oauth2/authorization/google") // Настройка страницы логина
);
return http.build();
}
}


Нюансы:
OAuth2 требует настройки клиентских данных (client ID и secret).
Поддерживается автоматический редирект на стороннюю страницу аутентификации.


5. LDAP Authentication

5.1 Описание
LDAP используется для аутентификации через службы каталогов, такие как Active Directory.

Пример конфигурации:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin()
.and()
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org");
return http.build();
}


Нюансы:
Требуется настроить LDAP сервер.
Используется в корпоративных приложениях.


Spring Security поддерживает множество способов аутентификации, начиная от традиционных форм логина и заканчивая современными подходами, такими как OAuth2 и JWT. Выбор подхода зависит от требований приложения:
Для веб-приложений подойдет форма логина.
Для REST API — JWT.
Для корпоративных систем — LDAP.



#Java #Training #Spring #Security #Security_Authority
Использование базы данных для хранения пользователей в Spring Security

Хранение пользователей в базе данных является наиболее распространённым способом управления аутентификацией в реальных приложениях. Это позволяет централизовать информацию о пользователях и их ролях, упрощая управление и обеспечивая безопасность.

1. Общая архитектура

Когда Spring Security использует базу данных для аутентификации, основные элементы выглядят следующим образом:
База данных: Хранит таблицы пользователей и ролей.
UserDetailsService: Загрузчик пользователей, который извлекает данные из базы данных.
PasswordEncoder: Обеспечивает хэширование паролей.
AuthenticationManager: Выполняет процесс аутентификации.
Роли и привилегии: Хранятся в базе для управления авторизацией.


2. Шаги по реализации

2.1 Настройка базы данных
Создайте базу данных и добавьте необходимые таблицы для хранения пользователей и их ролей. Рассмотрим пример на основе реляционной базы данных.

Пример SQL-схемы:
-- Таблица пользователей
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
enabled BOOLEAN NOT NULL
);

-- Таблица ролей
CREATE TABLE roles (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE
);

-- Таблица связи пользователей и ролей
CREATE TABLE user_roles (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);


Пример данных:
INSERT INTO users (username, password, enabled) VALUES 
('admin', '$2a$10$7a6yXl4bKh7QvXuUIhEY2eP2d6P5M6NmrkObWbxODeEM.gSUTZlVu', true), -- пароль: admin
('user', '$2a$10$w8y4/gM3/uF9Rf/5S1OejX.6M4KZt7eEPY2OnB9oRxCSU8Y4.jK8u', true); -- пароль: user

INSERT INTO roles (name) VALUES ('ROLE_ADMIN'), ('ROLE_USER');

INSERT INTO user_roles (user_id, role_id) VALUES
(1, 1), -- admin имеет роль ROLE_ADMIN
(2, 2); -- user имеет роль ROLE_USER
Пароли были закодированы с использованием BCryptPasswordEncoder.


2.2 Настройка приложения
Подключение к базе данных

Настройте подключение к базе данных в файле application.properties (или application.yml):

application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/spring_security_db
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update


Зависимости
Добавьте зависимости для работы с базой данных и Spring Security:

Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>


Gradle:
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'mysql:mysql-connector-java'


#Java #Training #Spring #Security #Security_BD
2.3 Реализация UserDetailsService
Spring Security использует интерфейс UserDetailsService для загрузки пользователей из базы данных. Реализуем его в нашем приложении.
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
public class CustomUserDetailsService implements UserDetailsService {

private final UserRepository userRepository;

public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserEntity userEntity = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("Пользователь не найден: " + username));

return User.builder()
.username(userEntity.getUsername())
.password(userEntity.getPassword())
.authorities(userEntity.getRoles().stream()
.map(role -> "ROLE_" + role.getName())
.toList())
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(!userEntity.isEnabled())
.build();
}
}


2.4 Создание Репозиториев
Создадим репозитории для работы с таблицами пользователей и ролей.


UserRepository:
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UserRepository extends JpaRepository<UserEntity, Long> {
Optional<UserEntity> findByUsername(String username);
}


RoleRepository:
import org.springframework.data.jpa.repository.JpaRepository;

public interface RoleRepository extends JpaRepository<RoleEntity, Long> {
}


2.5 Создание Сущностей
UserEntity:
import jakarta.persistence.*;
import java.util.Set;

@Entity
@Table(name = "users")
public class UserEntity {

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

@Column(nullable = false, unique = true)
private String username;

@Column(nullable = false)
private String password;

@Column(nullable = false)
private boolean enabled;

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

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


RoleEntity:
import jakarta.persistence.*;
import java.util.Set;

@Entity
@Table(name = "roles")
public class RoleEntity {

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

@Column(nullable = false, unique = true)
private String name;

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

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


#Java #Training #Spring #Security #Security_BD
2.6 Настройка Конфигурации Безопасности
Настроим SecurityConfig для использования пользовательской реализации UserDetailsService.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

private final CustomUserDetailsService customUserDetailsService;

public SecurityConfig(CustomUserDetailsService customUserDetailsService) {
this.customUserDetailsService = customUserDetailsService;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin()
.and()
.logout().permitAll();

return http.build();
}

@Bean
public AuthenticationManager authManager(HttpSecurity http, PasswordEncoder passwordEncoder)
throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder)
.and()
.build();
}

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


3. Тестирование

Теперь, когда настройка завершена:
Вы можете зарегистрировать новых пользователей, хэшировать их пароли с помощью BCryptPasswordEncoder и сохранять их в базу данных.
При попытке входа Spring Security будет извлекать пользователя из базы данных через CustomUserDetailsService.


#Java #Training #Spring #Security #Security_BD
Что выведет код?

class Parent1312 {
String name = "Parent";

void printName() {
System.out.println("Name: " + name);
}
}

class Child1312 extends Parent1312 {
String name = "Child";

@Override
void printName() {
System.out.println("Name: " + name);
}
}

public class Task131224_1 {
public static void main(String[] args) {
Parent1312 obj1 = new Child1312();
Child1312 obj2 = new Child1312();

System.out.println("Direct access:");
System.out.println("obj1.name: " + obj1.name);
System.out.println("obj2.name: " + obj2.name);

System.out.println("Method call:");
obj1.printName();
obj2.printName();
}
}


#Tasks
Вечер пятницы?🧐

https://t.me/Java_for_beginner_dev

#Mems
И еще немного про команды в JVM

1. Основные специальные символы

1.1. Символ * (звёздочка)
Используется для подстановки любого количества символов.
Применяется для работы с несколькими файлами.

javac src/com/example/*.java
Этот пример компилирует все файлы .java в указанной директории.


1.2. Символ ?
Подставляет любой один символ.
javac src/com/example/Fi?e.java
Компилирует файлы, чьи имена начинаются с Fi, заканчиваются на e и содержат один символ между ними (например, File.java, Fike.java).


1.3. Символы > и >>
>: перенаправляет вывод в файл, заменяя его содержимое.
>>: перенаправляет вывод в файл, добавляя данные в конец.

java -Xlog:gc > gc.log
Записывает логи сборщика мусора в файл gc.log, перезаписывая его содержимое.


java -Xlog:gc >> gc.log
Добавляет новые логи в конец файла gc.log.


1.4. Символ <
Перенаправляет ввод из файла.
java com.example.MyClass < input.txt
Передаёт содержимое файла input.txt как стандартный ввод для программы.


1.5. Символы | и &&
|: перенаправляет вывод одной команды на вход другой.
&&: выполняет следующую команду только если предыдущая завершилась успешно.

java com.example.MyClass | grep "Error"
Передаёт вывод программы в команду grep, которая фильтрует строки, содержащие Error.


javac MyClass.java && java MyClass
Компилирует MyClass.java и, если компиляция прошла успешно, запускает программу.


1.6. Символ &
Запускает процесс в фоновом режиме.
java com.example.MyClass &
Запускает программу в фоновом режиме, позволяя продолжать вводить команды.


1.7. Кавычки (", ', `)

Кавычки используются для обработки пробелов, спецсимволов и выполнения команд внутри строки.

Двойные кавычки ("): сохраняют пробелы, но позволяют интерполяцию переменных.
java -Dpath="C:\My Folder"


Одинарные кавычки ('): игнорируют интерполяцию переменных и спецсимволов.
java -Dpath='C:\My Folder'


Обратные кавычки (`): выполняют команду и подставляют её вывод.
java -Dtime=`date`


1.8. Символы []
Указывают диапазоны символов для подстановки.
javac src/[a-c]*.java
Компилирует все файлы, начинающиеся с букв a, b или c.


2. Пример комбинирования специальных символов

javac src/com/example/*.java && java -cp src com.example.Main > output.log


Этот пример:
Компилирует все файлы .java в указанной директории.
Если компиляция успешна, запускает класс Main.
Записывает вывод программы в файл output.log.


3. Особенности в разных ОС


Windows (CMD):

Некоторые символы требуют экранирования с помощью ^:
java -Dpath="C:\My^ Folder"


В PowerShell используется обратный апостроф (`) для экранирования:
java -Dpath="C:\My` Folder"


Linux и MacOS (Bash, Zsh):
Используются стандартные символы, такие как \ для экранирования.
java -Dpath="C:\My\ Folder"


4. Полезные советы

Если необходимо передать символы буквально (например, *, ?, или $), экранируйте их с помощью \:
java -Dspecial=\* com.example.Main


Используйте кавычки для обработки путей с пробелами:
javac -cp "lib/some library.jar" MyClass.java


#Java #Training #Medium #JVM_Commands
Настройка ролей и прав доступа в 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
Использование аннотаций в методах:
@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
Всем доброго субботнего утра!☀️

Как у Вас прошла неделя? Готовитесь к Новому году?🎄

А я для Вас на завтра готовлю то, что не успел реализовать в прошлое воскресение - CI/CD. 🔄
Все подробности завтра.


Всем хороших выходных!💪
This media is not supported in your browser
VIEW IN TELEGRAM
Всем доброго воскресения! 🖐

Сегодня в 16:00 я вновь жду всех Вас на встречу!

Темы сегодняшней встречи:
🔹 зачем таким как мы удаленный сервер и как его настроить для минимально приемлемой работы
🔹 что такое CI/CD и при чем тут Jenkins
🔹 вспомним о существовании Docker, потыкаем его в разные команды
🔹 создадим минимально рабочий проект на Spring и настроим его непрерывную интеграцию и непрерывное развертывание в контейнер
🔹 просто пообщаемся в хорошей компании IT-шников


Жду конечно же всех🫵
(но придут как всегда единицы😡)
Изучаем CI/CD. Метод для контейнеризации приложения в Docker через Jenkins. Встреча от 15.12.2024

Запись нашей сегодняшней встречи -
YOUTUBE
RUTUBE

Крайне благодарен всем кто пришел, за участие!💪

На сегодняшней встрече мы на примере, разобрали:
— что такое CI/CD и для чего он нужен.
— как поставить Java, Maven, Docker на удаленный сервер.
— как поставить и настроить для работы Jenkins.
— как создать простейшее веб-приложение и задеплоить его на сервер в Docker контейнер, через CI/CD и Jenkins


Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!

Ссылка на GitHub - https://github.com/Oleborn/CICDReserch

Всем хорошего настроения! 🫡✌️
JWT (JSON Web Token)

JWT (JSON Web Token) — это компактный и безопасный стандарт для передачи информации между сторонами в виде JSON-объекта. Он часто используется для аутентификации и передачи данных в веб-приложениях. JWT токены обладают рядом преимуществ, таких как легкость использования, самодостаточность (вся необходимая информация содержится внутри токена) и поддержка подписей для проверки подлинности.

1. Что такое JWT?

JWT представляет собой строку, состоящую из трех частей, разделенных точками (.):
xxxxx.yyyyy.zzzzz


Эти части соответствуют:
Header (заголовок) — метаинформация о токене.
Payload (полезная нагрузка) — данные, которые содержатся в токене.
Signature (подпись) — защита токена от подделки.


2. Структура JWT

2.1 Header
Заголовок содержит информацию о типе токена и алгоритме подписи.
{
"alg": "HS256",
"typ": "JWT"
}


alg — алгоритм подписи (например, HMAC-SHA256, RS256 и др.).
typ — тип токена (обычно "JWT").
Заголовок кодируется в формате Base64Url.


2.2 Payload
Полезная нагрузка содержит данные, которые передаются в токене. Эти данные называются "claims" (утверждения).

Они делятся на три типа:

Registered claims (зарегистрированные утверждения):
iss (issuer) — кто выдал токен.
sub (subject) — пользователь или субъект токена.
aud (audience) — для кого предназначен токен.
exp (expiration time) — время истечения токена (UNIX-время).
nbf (not before) — токен не должен использоваться до указанного времени.
iat (issued at) — время выдачи токена.
jti (JWT ID) — уникальный идентификатор токена.


Public claims (публичные утверждения): настраиваемые пользователем данные, такие как role, username и т.д.

Private claims (приватные утверждения): данные, специфичные для приложения, которые не входят в публичный стандарт.

{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"exp": 1701234567
}
Payload также кодируется в формате Base64Url.


2.3 Signature
Подпись обеспечивает целостность токена. Она создается путем использования:

Закодированных в Base64Url Header и Payload.
Секретного ключа.
Алгоритма подписи.


Пример создания подписи (при использовании алгоритма HMAC-SHA256):
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Результат (подпись) добавляется в конец токена.


3. Виды шифрования и алгоритмы

JWT может быть подписан или зашифрован:

3.1 Подписанные JWT
Подписанные токены защищены от изменения, но их содержимое можно прочитать. Используемые алгоритмы:

HMAC (симметричное шифрование):
Пример: HS256 (HMAC-SHA256).
Использует один общий секретный ключ для создания и проверки подписи.
Подходит для приложений с одним центром проверки.


RSA (асимметричное шифрование):

Пример: RS256 (RSA-SHA256).
Использует пару ключей: приватный для подписания и публичный для проверки.
Применяется в системах, где проверку подписи выполняют разные сервисы.


ECDSA (эллиптическая криптография):
Пример: ES256.
Более производительный, чем RSA, но с аналогичным подходом к подписи.


3.2 Зашифрованные JWT
Иногда требуется скрыть содержимое токена. Для этого используется JSON Web Encryption (JWE). Зашифрованные токены обеспечивают конфиденциальность данных.

Основные алгоритмы шифрования:
AES (например, A256GCM).
RSA (например, RSA-OAEP).
Шифрование выполняется с использованием публичного ключа, а расшифровка — с помощью приватного.


4. Как формируется JWT?

Создается Header.
Создается Payload с данными.
Заголовок и полезная нагрузка кодируются в формате Base64Url.
Создается Signature, используя заголовок, полезную нагрузку и секретный ключ.
Все части объединяются в строку через точки.


Пример токена:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImV4cCI6MTcwMTIzNDU2N30
.
sX5yQNjQp17l-lF6fBt6CXyP0NItBTppS-ANkSQ6jCk


#Java #Training #Spring #Security #JWT
5. Что необходимо для расшифровки и проверки?

5.1 Для подписи на основе HMAC:
Алгоритм (например, HS256).
Секретный ключ (shared secret).


5.2 Для подписи на основе RSA:

Алгоритм (например, RS256).
Публичный ключ (для проверки подписи).
Приватный ключ (для создания подписи, если вы являетесь сервером).


5.3 Для шифрования:

Алгоритм (например, AES256 или RSA-OAEP).
Публичный ключ (для расшифровки).


6. Преимущества JWT
Самодостаточность: Вся необходимая информация содержится в токене.
Безопасность: Подпись обеспечивает защиту от подделки.
Простота использования: Легко передается между клиентом и сервером.
Масштабируемость: Подходит для распределенных систем (например, микросервисов).


7. Уязвимости и меры безопасности
Использование слабых секретных ключей: Используйте сложные и длинные ключи.
Отсутствие проверки срока действия (exp): Убедитесь, что токен истекает через разумный период.
Применение неподходящих алгоритмов: Используйте надежные алгоритмы (например, RS256, HS256).
Утечка приватного ключа: Приватные ключи должны быть строго защищены.
XSS-атаки: Храните JWT в HttpOnly cookies, а не в localStorage.


8. Пример реализации на Java
Пример генерации и проверки JWT с использованием библиотеки jjwt (Java JWT):

Зависимость в pom.xml:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>


Генерация токена:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtExample {

private static final String SECRET_KEY = "your-secret-key";

public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 час
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}


Проверка токена:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;

public class JwtExample {

private static final String SECRET_KEY = "your-secret-key";

public static Claims validateToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
}


#Java #Training #Spring #Security #JWT
Что выведет код?

class Parent1612 {
private String message = "Parent";

public String getMessage() {
return message;
}
}

class Child1612 extends Parent1612 {
private String message = "Child";

@Override
public String getMessage() {
return message;
}
}

public class Task161224_1 {
public static void main(String[] args) {
Parent1612 obj = new Child1612 ();
System.out.println(obj.getMessage());
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
22%
Parent
67%
Child
11%
Ошибка компиляции
0%
null
И ведь правда...🤪😂

https://t.me/Java_for_beginner_dev

#Mems
Внедрение JWT-аутентификации в Spring Security

JWT (JSON Web Token) аутентификация — это популярный подход к обеспечению безопасности веб-приложений, особенно в REST API. Она позволяет передавать информацию о пользователе в токене и исключает необходимость поддерживать сессии на сервере.

1. Общий процесс JWT-аутентификации

Аутентификация пользователя: Клиент отправляет логин и пароль на сервер.
Генерация токена: После успешной аутентификации сервер создает JWT токен и возвращает его клиенту.
Доступ к защищенным ресурсам: Клиент отправляет токен в заголовке Authorization (Bearer <token>), чтобы получить доступ к ресурсам.
Проверка токена: Сервер проверяет токен при каждом запросе и предоставляет доступ только аутентифицированным пользователям.


2. Необходимые зависимости

Добавьте в pom.xml зависимости:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>


3. Шаги реализации JWT-аутентификации

3.1 Создание конфигурационного класса Spring Security
Создаем класс SecurityConfig для настройки Spring Security:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

private final JwtAuthenticationFilter jwtAuthenticationFilter;

public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/login", "/auth/register").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
}

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

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}


#Java #Training #Spring #Security #JWT