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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Все знают, что он существует, но лично никто не видел...

https://t.me/Java_for_beginner_dev

#Mems
Base64 в Java Crypto API

Base64 — это алгоритм кодирования двоичных данных в текстовый формат с использованием 64 символов ASCII. Он используется для представления бинарных данных в виде строк, удобных для передачи по сетевым протоколам и хранения в текстовых форматах. В Java Crypto API Base64 часто применяется для кодирования криптографических ключей, сертификатов и других бинарных данных.

Как работает Base64

Base64 берет 3 байта (24 бита) входных данных и преобразует их в 4 символа из 64-символьного алфавита.

Алфавит Base64 включает:
Латинские буквы: A-Z и a-z (52 символа)
Цифры: 0-9 (10 символов)
Два специальных символа: + и / (или - и _ в URL-совместимой версии)
Заполнитель = (если входные данные не кратны 3 байтам)


Пример кодирования
Допустим, у нас есть строка "Man":

Преобразуем в ASCII-коды:
M = 77, a = 97, n = 110


Переводим в двоичный вид (каждый символ занимает 8 бит):
M     a     n
01001101 01100001 01101110


Разбиваем на 6-битные блоки (24 бита → 4 группы по 6 бит):
010011 010110 000101 101110


Соотносим с таблицей Base64:
010011 → T
010110 → W
000101 → F
101110 → u
Результат кодирования: "TWFu"


Если входные данные не кратны 3 байтам, добавляются =:
"Ma" (2 байта) → TWE=
"M" (1 байт) → TQ==


Base64 в Java


Java предоставляет встроенный класс Base64 в пакете java.util, начиная с Java 8.

Кодирование строки в Base64
import java.util.Base64;

public class Base64Example {
public static void main(String[] args) {
String originalString = "Hello, Java Crypto API!";
String encodedString = Base64.getEncoder().encodeToString(originalString.getBytes());
System.out.println("Encoded: " + encodedString);
}
}


Вывод:
Encoded: SGVsbG8sIEphdmEgQ3J5cHRvIEFQISTCoA==


Декодирование Base64

import java.util.Base64;

public class Base64DecodeExample {
public static void main(String[] args) {
String encodedString = "SGVsbG8sIEphdmEgQ3J5cHRvIEFQISTCoA==";
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String decodedString = new String(decodedBytes);
System.out.println("Decoded: " + decodedString);
}
}


Вывод:
Decoded: Hello, Java Crypto API!


Варианты Base64 в Java

В Java есть три основных варианта Base64:

1. Base64.getEncoder() и Base64.getDecoder() (обычная версия)
Использует стандартный алфавит A-Z, a-z, 0-9, +, / и =.

Пример:
Base64.Encoder encoder = Base64.getEncoder();
Base64.Decoder decoder = Base64.getDecoder();

String encoded = encoder.encodeToString("Test".getBytes());
String decoded = new String(decoder.decode(encoded));

System.out.println("Encoded: " + encoded);
System.out.println("Decoded: " + decoded);


2. Base64.getUrlEncoder() и Base64.getUrlDecoder() (для URL)
Использует безопасный для URL алфавит A-Z, a-z, 0-9, -, _ (заменяет + на - и / на _, убирает =).

Пример:
Base64.Encoder urlEncoder = Base64.getUrlEncoder();
Base64.Decoder urlDecoder = Base64.getUrlDecoder();

String encoded = urlEncoder.encodeToString("https://example.com".getBytes());
String decoded = new String(urlDecoder.decode(encoded));

System.out.println("Encoded URL: " + encoded);
System.out.println("Decoded URL: " + decoded);


3. Base64.getMimeEncoder() и Base64.getMimeDecoder() (для MIME)
Форматирует выходные данные в 76-символьные строки, разделенные \r\n, подходит для шифрования PGP, email-передачи.

Пример:
Base64.Encoder mimeEncoder = Base64.getMimeEncoder();
Base64.Decoder mimeDecoder = Base64.getMimeDecoder();

String encoded = mimeEncoder.encodeToString("Example MIME data".getBytes());
String decoded = new String(mimeDecoder.decode(encoded));

System.out.println("Encoded MIME: " + encoded);
System.out.println("Decoded MIME: " + decoded);


#Java #Training #Medium #Java_Crypto_API #Base64
Где применяется Base64

Передача бинарных данных в текстовом формате
Встраивание изображений в HTML и CSS:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />

Кодирование бинарных данных в JSON

Шифрование и подписи в криптографии
Используется для кодирования RSA-ключей, хэшей, токенов JWT

Пример работы с шифрованием AES:

byte[] encryptedData = encryptAES("Hello".getBytes(), secretKey);
String base64Encoded = Base64.getEncoder().encodeToString(encryptedData);


HTTP-заголовки и авторизация
Basic Auth:
String auth = "user:password";
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
String header = "Authorization: Basic " + encodedAuth;


Передача данных по email (MIME)
Base64 используется в email-кодировании, Content-Transfer-Encoding: base64

Сериализация бинарных данных
Применяется для кодирования файлов в JSON, передаваемых через API.

Ограничения и недостатки

Увеличение размера
Base64 увеличивает размер данных на ~33% (3 байта → 4 символа).

Не защищает данные
Base64 — это не шифрование и не хэширование. Оно только преобразует данные в строковый вид, но не защищает их.

Обратимость
Закодированные данные легко декодируются, поэтому Base64 не подходит для хранения паролей.

#Java #Training #Medium #Java_Crypto_API #Base64
Что выведет код

public class Task260225 {
public static void main(String[] args) {
String value = "10";
print(value);
print((byte) value);
print((Object) value);
}

public static void print(String x) {
System.out.println("String");
}

public static void print(byte x) {
System.out.println("byte");
}

public static void print(Object x) {
System.out.println("Object");
}
}


#Tasks
#Mems. Сеньор разработчик решил воспользоваться секретным заклинанием.
Интересно остались ли те кто сам пишет код? 🧐 🤣

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Что такое default метод в интерфейсе?
Anonymous Quiz
2%
Абстрактный метод
4%
Статический метод
93%
Метод с реализацией по умолчанию
0%
Приватный метод
Криптографические протоколы (TLS/SSL, HMAC) в Java Crypto API

Криптографические протоколы обеспечивают безопасную передачу данных по сети, защищая их от перехвата, подделки и модификации. В Java Crypto API основными протоколами являются TLS/SSL для защиты соединений и HMAC для проверки целостности данных.

TLS/SSL

TLS (Transport Layer Security) и устаревший SSL (Secure Sockets Layer) — это криптографические протоколы, обеспечивающие безопасное соединение между клиентом и сервером.
TLS заменил SSL, так как SSL имеет уязвимости. На сегодня актуальная версия — TLS 1.3.


Как TLS/SSL защищает соединение

Аутентификация сервера — клиент проверяет подлинность сервера с помощью SSL-сертификата.
Шифрование — передача данных в зашифрованном виде с помощью алгоритмов AES, ChaCha20, RSA.
Целостность — защита данных от подмены с помощью HMAC (Message Authentication Code).


TLS и HTTPS

HTTPS (HyperText Transfer Protocol Secure) — это HTTP + TLS/SSL.
Гарантирует шифрование и проверку подлинности при доступе к сайтам.
В браузере замок означает, что соединение защищено TLS.


Как работает TLS в Java

Java использует библиотеку JSSE (Java Secure Socket Extension) для работы с TLS/SSL.

Установление защищенного HTTPS-соединения

Для отправки HTTPS-запроса в Java используется HttpsURLConnection:
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class HttpsClient {
public static void main(String[] args) throws Exception {
URL url = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

// Проверка сертификата
conn.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());
conn.setRequestMethod("GET");

// Чтение ответа
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
in.close();
}
}


Использование своего SSLContext

Для работы с кастомными сертификатами можно использовать SSLContext:
import javax.net.ssl.*;
import java.io.FileInputStream;
import java.security.KeyStore;

public class CustomSSLContext {
public static void main(String[] args) throws Exception {
String keystorePath = "keystore.jks"; // Файл хранилища ключей
String keystorePassword = "password";

// Загрузка ключей
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystorePath), keystorePassword.toCharArray());

// Инициализация KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keystorePassword.toCharArray());

// Создание SSL-контекста
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);

// Использование SSLContext
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
}
}



#Java #Training #Medium #Java_Crypto_API #TLS #SSL
HMAC (Hash-based Message Authentication Code)

HMAC — это механизм проверки целостности данных и аутентификации отправителя.
Основан на криптографических хеш-функциях (SHA-256, SHA-512).
Использует секретный ключ, что делает его безопаснее обычного хеширования.


Как работает HMAC
Клиент и сервер имеют секретный ключ.
Отправитель вычисляет HMAC от сообщения с этим ключом.
Получатель повторно вычисляет HMAC и проверяет совпадение.


Реализация HMAC в Java

Генерация HMAC (SHA-256)

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class HmacExample {
public static void main(String[] args) throws Exception {
String message = "Hello, Java Crypto API!";
String secretKey = "my_secret_key";

// Создание HMAC SHA-256
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
mac.init(keySpec);

// Вычисление HMAC
byte[] hmacBytes = mac.doFinal(message.getBytes());
String hmacBase64 = Base64.getEncoder().encodeToString(hmacBytes);

System.out.println("HMAC (Base64): " + hmacBase64);
}
}


Вывод:
HMAC (Base64): q8phcxg9DpPpMfKkczjRkkv6OiOBv2YoTbYJ46qZaYc=


Проверка HMAC
public static boolean verifyHmac(String message, String receivedHmac, String secretKey) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
mac.init(keySpec);

// Вычисляем HMAC заново
byte[] hmacBytes = mac.doFinal(message.getBytes());
String computedHmac = Base64.getEncoder().encodeToString(hmacBytes);

// Сравниваем с полученным HMAC
return computedHmac.equals(receivedHmac);
}


Где применяется HMAC


Аутентификация API-запросов
Многие API используют HMAC для подписи запросов (например, AWS, Binance API).
Клиент вычисляет HMAC и отправляет вместе с запросом.
Сервер проверяет правильность HMAC.


Целостность сообщений в TLS/SSL
В TLS 1.2 использовался HMAC для проверки целостности передаваемых данных.

Подпись JSON Web Tokens (JWT)
JWT использует HMAC для подписи (HMAC-SHA256).
Сервер проверяет подпись перед обработкой запроса.


Хранение паролей в базе данных
HMAC можно использовать для защиты паролей перед хешированием.

#Java #Training #Medium #Java_Crypto_API #HMAC
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Продолжим изучение Spring в углубленных статьях.

Объектно-реляционное отображение (ORM - Object-Relational Mapping)

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


ORM (Object-Relational Mapping) — это технология, которая позволяет программам работать с реляционной базой данных, используя объектно-ориентированный подход. Она автоматически преобразует объекты языка программирования (например, Java-классы) в строки таблиц базы данных и обратно.

Основные задачи ORM:
Автоматическое сопоставление объектов с таблицами базы данных.
Управление состояниями объектов (создание, обновление, удаление, чтение).
Оптимизация работы с БД за счёт кеширования и ленивой загрузки.
Генерация SQL-запросов без необходимости их явного написания.


2. Как работает ORM?


Работа ORM состоит из нескольких ключевых этапов:
2.1. Анализ классов сущностей
При запуске приложения ORM-провайдер анализирует классы, помеченные аннотациями (например, @Entity в JPA/Hibernate), и строит их соответствие с таблицами базы данных.

Пример класса-сущности:
Редактировать
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "username", nullable = false)
private String username;

@Column(name = "email", unique = true)
private String email;
}


ORM анализирует этот класс и определяет:
Таблица называется users.
Поле id — первичный ключ с автоинкрементом.
Поле username обязательно (nullable = false).
Поле email должно быть уникальным.


2.2. Генерация SQL-запросов

При выполнении операций с объектами ORM автоматически генерирует SQL-запросы.

Например:
User user = new User();
user.setUsername("john_doe");
user.setEmail("john@example.com");
userRepository.save(user);


Этот код сгенерирует SQL-запрос:
INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com');


Если позже мы изменим объект и сохраним его, ORM выполнит UPDATE:
user.setEmail("new_email@example.com");
userRepository.save(user);


UPDATE users SET email = 'new_email@example.com' WHERE id = 1;
Разработчик не пишет SQL-код вручную — ORM делает это автоматически.


2.3. Управление состояниями объектов
Каждый объект, управляемый ORM, может находиться в одном из четырёх состояний:
Transient - Объект создан, но не сохранён в БД.
Managed - Объект привязан к контексту EntityManager.
Detached - Объект был сохранён, но теперь отсоединён.
Removed - Объект помечен для удаления.

Пример:
User user = new User(); // Transient
user.setUsername("Alice");

entityManager.persist(user); // Managed
entityManager.detach(user); // Detached
entityManager.remove(user); // Removed


2.4. Кеширование
ORM использует кеширование для уменьшения нагрузки на базу данных.
Первичный кеш (L1 Cache): Внутри EntityManager. Если объект уже загружен, он не запрашивается заново.
Вторичный кеш (L2 Cache): Глобальный кеш, доступный для всех EntityManager.


Пример:
User user1 = entityManager.find(User.class, 1); // SQL выполняется
User user2 = entityManager.find(User.class, 1); // Берётся из кеша
Первый запрос загрузит данные из БД, второй возьмёт их из памяти.


2.5. Ленивые (Lazy) и Жадные (Eager) загрузки
ORM позволяет загружать связанные данные жадно (EAGER) или лениво (LAZY).

Пример:
@Entity
public class User {
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
}


LAZY — данные загружаются только при обращении к orders.
EAGER — данные загружаются сразу при запросе User.

User user = userRepository.findById(1L).get();
List<Order> orders = user.getOrders(); // SQL-запрос будет только здесь, если Lazy


3. Виды ORM и их отличия

3.1. Полноценные ORM (с динамическим SQL)
Автоматически генерируют SQL-запросы и управляют объектами:
Hibernate (Spring Data JPA)
EclipseLink
TopLink


3.2. Полу-ORM (с маппингом, но без генерации SQL)
Работают с SQL, но помогают преобразовывать результаты в объекты:
MyBatis (требует явного написания SQL)

3.3. Lightweight ORM (обёртки над JDBC)
Spring JdbcTemplate — облегчённая обёртка над JDBC, но без автоматического маппинга.

#Java #Training #Spring #SpringDataJPA #ORM
Что выведет код?

public class Task270225 {
public static void main(String[] args) {
List<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);

(list).removeFirst();
list.remove(1);

System.out.println(list);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
13%
[1, 3]
35%
[2]
26%
[3]
26%
[2, 3]
Если она его убьет в аду, ее заставят еще один блокнот написать? 🧐 🤣

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой метод используется для преобразования строки в нижний регистр?
Anonymous Quiz
81%
toLowerCase()
7%
toUpperCase()
7%
toLower()
5%
convertToLower()
EntityManager

EntityManager — это ключевой интерфейс в Java Persistence API (JPA), который управляет жизненным циклом сущностей (entities). Он предоставляет методы для выполнения операций CRUD (Create, Read, Update, Delete) с сущностями, а также для управления транзакциями и выполнения запросов к базе данных. EntityManager действует как мост между объектами Java и базой данных, автоматически преобразуя объекты в записи базы данных и наоборот.

Как запускается EntityManager в Spring?

Для работы EntityManager в Spring требуется настройка нескольких ключевых объектов. Вот основные компоненты, участвующие в его запуске:

DataSource:
Это объект, представляющий соединение с базой данных. Он содержит информацию о URL, имени пользователя, пароле и других параметрах подключения.

Пример настройки в Spring:
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}


LocalContainerEntityManagerFactoryBean:
Это фабрика для создания EntityManagerFactory. Она настраивает JPA и связывает DataSource с провайдером JPA (например, Hibernate).

Пример настройки:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return em;
}


EntityManagerFactory:
Это фабрика для создания EntityManager. Она управляет метаданными сущностей и настройками JPA.
Создается на основе LocalContainerEntityManagerFactoryBean.

PlatformTransactionManager:
Управляет транзакциями. В Spring используется JpaTransactionManager, который интегрируется с EntityManager.

Пример настройки:
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}


EntityManager:
Создается через EntityManagerFactory. В Spring обычно инжектируется с помощью @PersistenceContext.

Как настраивается EntityManager и для чего нужна его настройка?

Настройка EntityManager необходима для:

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


Типовые случаи настройки:
Использование Hibernate как провайдера JPA:
Настройка LocalContainerEntityManagerFactoryBean с указанием HibernateJpaVendorAdapter.


Пример:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.domain");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return em;
}


Настройка кэширования второго уровня:
Включается через свойства JPA или Hibernate.

Пример:
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory


Основные функции EntityManager

Управление жизненным циклом сущностей:
persist(): Добавляет сущность в контекст persistence.
merge(): Обновляет сущность в базе данных.
remove(): Удаляет сущность из базы данных.
find(): Извлекает сущность по первичному ключу.


Выполнение запросов:
createQuery(): Создает JPQL-запрос.
createNativeQuery(): Создает нативный SQL-запрос.


Управление транзакциями:
getTransaction(): Возвращает объект EntityTransaction для управления транзакциями.

Синхронизация с базой данных:
flush(): Синхронизирует изменения с базой данных.
refresh(): Обновляет состояние сущности из базы данных.

#Java #Training #Hard #Spring #SpringDataJPA #EntityManager
Основные методы EntityManager

persist(Object entity):
Добавляет сущность в контекст persistence. Сущность будет сохранена в базе данных при вызове flush() или завершении транзакции.

merge(Object entity):
Обновляет сущность в базе данных. Если сущность не существует, она будет создана.

remove(Object entity):
Удаляет сущность из базы данных.

find(Class<T> entityClass, Object primaryKey):

Извлекает сущность по первичному ключу.

createQuery(String qlString):
Создает JPQL-запрос для работы с сущностями.

flush():
Синхронизирует изменения с базой данных.

refresh(Object entity):
Обновляет состояние сущности из базы данных.

getTransaction():
Возвращает объект EntityTransaction для управления транзакциями.

Как работает EntityManager под капотом?

Контекст Persistence:
EntityManager работает в рамках контекста persistence, который отслеживает состояние сущностей.
Контекст persistence может быть транзакционным (в рамках одной транзакции) или расширенным (в рамках нескольких транзакций).

Отслеживание изменений:
EntityManager отслеживает изменения в сущностях (например, изменение полей) и автоматически генерирует SQL-запросы для синхронизации с базой данных.

Кэширование:
EntityManager использует кэш первого уровня (в рамках одного контекста persistence) для хранения сущностей. Это позволяет избежать повторных запросов к базе данных.

Генерация SQL:
EntityManager использует метаданные сущностей (например, аннотации @Entity, @Column) для генерации SQL-запросов.

Управление транзакциями:
EntityManager интегрируется с EntityTransaction для управления транзакциями. Все операции выполняются в рамках транзакции.

Синхронизация с базой данных:
При вызове flush() все изменения в сущностях синхронизируются с базой данных. Это может происходить автоматически при завершении транзакции.

Ленивая загрузка:
EntityManager поддерживает ленивую загрузку (lazy loading) для связанных сущностей, что позволяет оптимизировать производительность.


#Java #Training #Hard #Spring #SpringDataJPA #EntityManager
#Mems. Буду откладывать сразу на неделю вперед.
Please open Telegram to view this post
VIEW IN TELEGRAM