Телеграм

Библиотека Java разработчика

@BookJava Программирование и разработка
РКН: проверяем Не иноагент
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP

Статистика обновлена 12.11.2026 в 22:03 · 1 просмотр страницы · Хотите больше просмотров?

Подписчики9 963
Охват поста878 9% от подписчиков
ERR за месяц8,81%
ERR за 24 часа4,77%

Динамика за 30 дней

Рекламные публикации

Рекламных публикаций не найденоЗа последнее время мы не нашли на площадке ни одного рекламного поста.

Последние публикации

Все посты канала →
Библиотека Java разработчика tg10 тыс. подписчиков
Открыть пост ↗
В асинхронных или веб-сервисах на реактиве нужно быть осторожным: SecurityContext не “переходит” автоматически в новые потоки. Для этого используют SecurityContextRepository и специальные методы в WebFlux.

⚠️ Важно: не храните SecurityContext в сессии, если у вас stateless-приложение (REST API). Вместо сессии используйте JWT или OAuth 2.0.

🧠 5. Авторизация: FilterSecurityInterceptor & AccessDecisionManager
FilterSecurityInterceptor запускается в конце цепочки фильтров и проверяет доступ к URL. Он запрашивает у SecurityMetadataSource список необходимых ролей для данного эндпоинта (Spring на основании @PreAuthorize, HttpSecurity конфигурации или XML). Затем передаёт дело в AccessDecisionManager (по умолчанию AffirmativeBased), который опрашивает список AccessDecisionVoter (например, RoleVoter для проверок ролей, WebExpressionVoter для SpEL).


FilterSecurityInterceptor
└─> SecurityMetadataSource (что нужно: ROLE_ADMIN)
└─> AccessDecisionManager.vote()
├─ RoleVoter.vote() → совпадает?
└─ WebExpressionVoter.vote() → SpEL-выражения?


Если хотя бы один голос “grant”, AffirmativeBased отпускает запрос (по умолчанию). Можно менять стратегию на Consensus или Unanimous.

💡 Трюк: чтобы локально протестировать SecurityContext, можно в тестах использовать аннотацию @WithMockUser(roles = "ADMIN") и проверять, что нужный эндпоинт доступен.

🧠 6. Аннотации & Method Security
Помимо URL-уровня, есть методная проверка:


@EnableMethodSecurity // (Spring Boot 3+) вместо @EnableGlobalMethodSecurity
public class SecurityConfig { ... }

// Где-то в сервисе:
@PreAuthorize("hasRole('ADMIN') and #id == principal.id")
public void deleteUser(Long id) { ... }


* 📌 @PreAuthorize / @PostAuthorize / @Secured / @RolesAllowed — все используют тот же механизм Voter’ов, но проверяют уже на методах сервиса.
* 💡 Совет: включайте методную безопасность только там, где действительно нужна тонкая грануляция.

🧠 7. Хранение паролей & PasswordEncoder
С Java 17+ используйте PasswordEncoder с алгоритмами Argon2 или BCrypt:


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


⚠️ Никогда не храните пароли в открытом виде и не используйте MD5/SHA-1 — они считаются небезопасными.

🧠 8. Stateless vs Stateful

* Stateful (Сессии): Spring создаёт HTTP-сессию, а SecurityContextPersistenceFilter хранит контекст в сессии. Удобно для монолитов с классическим web-приложением.
* Stateless (JWT/OAuth2): убираем SessionCreationPolicy.STATELESS, используем BearerTokenAuthenticationFilter, аутентификация и авторизация проверяются по JWT в каждом запросе.

💡 Современный стек (Spring Boot 3+):

1. Настраиваем SecurityFilterChain с oauth2ResourceServer().jwt().
2. Подключаем spring-boot-starter-oauth2-resource-server.
3. Указываем issuer-uri или jwk-set-uri в application.yml.


spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://keycloak.example.com/realms/myrealm


🧠 9. Подпись запросов & CSRF

* По умолчанию CSRF включён для “форменных” запросов (POST, PUT, DELETE). Для stateless-API его обычно отключают:


http.csrf().disable();

* Если используете формы, не забудьте добавить в шаблон:


<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>


⚠️ Внимание: не отключайте CSRF, если ваше приложение использует сессии и cookie на фронтенде!

💡 Совет по отладке: включите логирование фильтров:


logging.level.org.springframework.security=DEBUG


Тогда в логах вы увидите, как проходит запрос через каждый фильтр и где происходит отказ.

📲 Мы в MAX

👉@BookJava
👁 408 👍 1🔥 1 ↻ 10 вчера в 19:43
Библиотека Java разработчика tg10 тыс. подписчиков
Открыть пост ↗
🎥 Вебинар: Пишем веб-сервер на Java
Напишем HTTP-сервер на чистой Java и разберём, как запрос от браузера попадает в обработчик.

🗣 О чём поговорим:
- Как браузер и сервер обмениваются данными: TCP-соединение, HTTP-запрос и ответ.
- Как принять соединение через ServerSocket и разобрать строку запроса и заголовки.
- Как добавить маршруты, отдавать HTML и JSON, обрабатывать GET и POST.
- Как обслуживать несколько клиентов одновременно с помощью пула потоков.
- Чем написанный сервер отличается от встроенного HttpServer в JDK и какую работу берёт на себя Spring.

💪 Результат урока:
Вы напишете работающий HTTP-сервер без фреймворков и сторонних библиотек и проследите путь запроса от браузера до обработчика. Это поможет разобраться, на каких механизмах строится работа с веб-запросами в сервлетах и Spring MVC.

👉 Для участия зарегистрируйтесь: https://vk.cc/d3O00p

Урок проходит в преддверии старта курса «Java-разработчик».На курсе вы изучите язык Java, базы данных, многопоточность, серверную разработку и современные инструменты, которые используют работодатели.

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👁 475 👍 1 ↻ 6 вчера в 08:23
Библиотека Java разработчика tg10 тыс. подписчиков
Открыть пост ↗
📌 Spring Security: основная архитектура

🧠 1. SecurityFilterChain & FilterChainProxy
Spring Security строит всё вокруг цепочки фильтров (FilterChainProxy). При запросе к приложению запрос проходит через набор фильтров, каждый из которых отвечает за свой кусок логики:

* ⚙️ ChannelProcessingFilter – перенаправление на HTTPS, если нужно.
* ⚙️ SecurityContextPersistenceFilter – загружает/сохраняет SecurityContext (где хранится Authentication).
* ⚙️ UsernamePasswordAuthenticationFilter – обрабатывает форму логина (если вы используете formLogin).
* ⚙️ BasicAuthenticationFilter – поддерживает HTTP Basic (для REST).
* ⚙️ BearerTokenAuthenticationFilter (Spring Boot 3+) – для JWT/OAuth2 Bearer-токенов.
* ⚙️ ExceptionTranslationFilter – перехватывает AccessDeniedException и AuthenticationException, перенаправляет на страницу логина или возвращает 401.
* ⚙️ FilterSecurityInterceptor – проверяет, есть ли у аутентифицированного пользователя разрешение (ROLE_*) для доступа к ресурсу.

Каждый фильтр решает конкретную задачу, и порядок важен: если, например, фильтр авторизации (FilterSecurityInterceptor) стоит раньше, чем фильтр аутентификации, вы получите неожиданный отказ.

💡 Современный подход (Spring Boot 3+):


@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth2 -> oauth2.jwt()); // JWT из OIDC/JWK
return http.build();
}


Таким образом вы сами управляете порядком фильтров и включаете только нужные.

🧠 2. AuthenticationManager & ProviderManager
Когда UsernamePasswordAuthenticationFilter (или другой аутентификатор) получает учётные данные, он создает UsernamePasswordAuthenticationToken с неверифицированными (unauthenticated) флагом. Затем передаёт этот токен в AuthenticationManager:


UsernamePasswordAuthenticationFilter → AuthenticationManager.authenticate()


AuthenticationManager по умолчанию — это ProviderManager, который хранит список AuthenticationProvider (например, DaoAuthenticationProvider для UserDetailsService или JwtAuthenticationProvider для токенов). Каждый Provider пытается аутентифицировать токен, и если успешно, возвращает уже аутентифицированный Authentication с authorities.

📌 Совет: если нужно добавить кастомную проверку (например, MFA), реализуйте свой AuthenticationProvider и зарегистрируйте его перед DaoAuthenticationProvider.

🧠 3. UserDetailsService & UserDetails
DaoAuthenticationProvider опирается на UserDetailsService (или ReactiveUserDetailsService в WebFlux), чтобы получить UserDetails (имя, пароль, роли, статус аккаунта). В Java 17+ можно пользоваться Map.of(...) или List.of(...), но в реальных проектах лучше хранить в БД через JPA/Hibernate.


@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository repo;
@Override
public UserDetails loadUserByUsername(String username) {
UserEntity user = repo.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return User.withUsername(user.getUsername())
.password(user.getPassword())
.authorities(user.getRoles().toArray(new String[0]))
.accountLocked(!user.isAccountNonLocked())
.build();
}
}


🧠 4. SecurityContext & SecurityContextHolder
После успешной аутентификации фильтр устанавливает SecurityContext в SecurityContextHolder. По умолчанию используется стратегия MODE_THREADLOCAL, т.е. контекст привязан к текущему потоку.


SecurityContextHolder.getContext().setAuthentication(authenticatedToken);


📲 Мы в MAX

👉@BookJava
👁 567 👍 2❤ 1 💬 1 ↻ 16 10 ноября