Разбираем магических зверей безопасности: AuthZ: abac/rbac, AuthN и 2FA
Вы знаете, что меня действительно выбивает из колеи забавит? Даже люди, которые давно работают в IT, путают аутентификацию и авторизацию. На пару проектах я столкнулся с тем, что некоторые ребята, которые работают в индустрии годами, не видят разницы между этими двумя понятиями. И это не просто «я офигеваю» озадачивает — это может быть опасно для безопасности систем, так как из за ложного определения мысли производят совсем не однозначные выводы.
Аутентификация (AuthN) — это способ подтвердить, что вы действительно тот, за кого себя выдаете. Это паспорт в цифровом мире: пароли, различная биометрия и другие экзотические способы — все это примеры аутентификации. Это как сказать: «Привет, это я!»
Авторизация (AuthZ) — это уже другой зверь. Это про то, что вы можете делать после того, как подтвердили свою личность. Представьте, что вы вошли в интернет-магазин. А вот теперь вопрос: можете ли вы просто просматривать товары, добавлять их в корзину или у вас есть доступ к админ-панели для изменения ассортимента? Это и есть авторизация — правила, которые определяют, какие действия вам доступны.
Зачем важно понимать разницу? Потому что, когда путаются эти понятия, возникают большие проблемы. Например, если вы путаете, кто может войти в систему (аутентификация) с тем, что этот пользователь может делать (авторизация), вы открываете двери для множества уязвимостей. Так что давайте раз и навсегда проясним: аутентификация и авторизация — это разные вещи, и понимать их разницу важно для обеспечения безопасности вашего ПО. Также очень классно разбирают данный вопрос в статье Authn vs. authz: How are they different? By Cloudflare!
Аутентификация (AuthN)
Прежде чем пользователи смогут взаимодействовать с вашим ПО, необходимо убедиться, что они являются теми, за кого себя выдают. Это и есть аутентификация (Authentication, AuthN). Примеры с паролем один из базовых, скажем так один из способов первого фактора.
Простой пример аутентификации на spring security который мало вероятно будет сейчас в Production! Но как пример для наглядного понимания имеет место быть, далее в статье буду применять простые снипеты и оставлять ссылки на более богатые варианты =)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
Достаточно хороший подход расписан в этом варианте и еще более информативнее в данной репе.
Как вы знаете современные системы безопасности все чаще переходят к использованию двухфакторной аутентификации (2FA) для повышения уровня защиты. Однофакторная аутентификация, такая как использование только пароля, больше не считается достаточно надежной из-за множества уязвимостей, связанных с паролями (например, их кража или перебора).
2FA добавляет дополнительный уровень безопасности, требуя второй способ проверки личности пользователя. Обычно это второй фактор из другой категории, например:
Что-то, что вы знаете: Пароль или PIN-код.
Что-то, что у вас есть: Смартфон или токен.
Что-то, что вы являетесь: Биометрические данные, такие как отпечатки пальцев или распознавание лица.
Отправка СМС
public class TwoFactorAuthenticationService {
// Метод для отправки SMS
public void sendSmsCode(String phoneNumber) {
String code = generateCode();
// Логика для отправки SMS
SmsSender.send(phoneNumber, "Ваш код подтверждения: " + code);
// Сохранение кода в базе данных или кэше
saveCode(phoneNumber, code);
}
// Генерация случайного кода
private String generateCode() {
// Логика генерации кода
return String.valueOf(new Random().nextInt(999999));
}
// Сохранение кода
private void saveCode(String phoneNumber, String code) {
// Логика сохранения кода (например, в базе данных или кэше)
CodeRepository.save(phoneNumber, code);
}
}
Проверка той самой СМС
@RestController
@RequiredArgsConstructor
public class TwoFactorAuthenticationController {
private TwoFactorAuthenticationService twoFactorAuthService;
// Метод для проверки кода
@PostMapping("/verifyCode")
public ResponseEntity verifyCode(@RequestParam String phoneNumber, @RequestParam String code) {
boolean isCodeValid = twoFactorAuthService.verifyCode(phoneNumber, code);
if (isCodeValid) {
return ResponseEntity.ok("Код подтвержден успешно");
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Неверный код");
}
}
}
@Service
public class TwoFactorAuthenticationService {
// Метод для проверки кода
public boolean verifyCode(String phoneNumber, String code) {
String savedCode = getCode(phoneNumber);
return code.equals(savedCode);
}
// Получение кода из базы данных или кэша
private String getCode(String phoneNumber) {
// Логика получения кода
return CodeRepository.findByPhoneNumber(phoneNumber);
}
}
Да да это все еще псевдокод, тут этот момент разбирается более наглядно.
Понятное дело что 2FA это не предел, не зря ведь есть термин MFA и тут уже все зависит от потребности бизнеса конкретному к вашему ПО.
Авторизация (AuthZ)
После того как пользователь прошел аутентификацию, следующей важной задачей является авторизация (Authorization, AuthZ). Авторизация определяет, что пользователь может делать в системе, к каким ресурсам у него есть доступ и какие действия он может выполнять. Представьте, что вы вошли в интернет-магазин. А вот теперь вопрос: можете ли вы просто просматривать товары, добавлять их в корзину или у вас есть доступ к админ-панели для изменения ассортимента? Это и есть авторизация — правила, которые определяют, какие действия вам доступны.
Role-Based Access Control (RBAC)
RBAC, или управление доступом на основе ролей, предоставляет доступ к ресурсам в зависимости от ролей (пользователь, модератор, администратор и так далее), назначенных пользователю. Это один из наиболее распространенных методов авторизации.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/", "/home").permitAll()
.requestMatchers("/user/**").hasRole("USER")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
Attribute-Based Access Control (ABAC)
ABAC, или управление доступом на основе атрибутов, предоставляет доступ на основе атрибутов пользователя, ресурсов и окружающей среды. Этот метод позволяет более гибко управлять доступом.
// Пример реализации ABAC может включать сложные правила на основе атрибутов,
// таких как должность пользователя, время дня или местоположение.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/", "/home").permitAll()
.requestMatchers("/user/**").access("hasRole('USER') and hasIpAddress('192.168.1.0/24')")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
// Здесь мы указываем, что доступ к URL, начинающимся с "/user/**",
// разрешен только пользователям с ролью "USER" и IP-адресом из подсети
// "192.168.1.0/24". Это пример использования атрибутов для контроля доступа.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/", "/home").permitAll()
.requestMatchers("/user/**").access("hasRole('USER') and hasIpAddress('192.168.1.0/24')")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
Таким образом, современные системы безопасности могут использовать различные подходы к авторизации, чтобы обеспечить гибкость и защиту. Также более наглядный пример RBAC/ABAC можно найти в данном материале.
Вот что в итоге Карл!
Аутентификация и авторизация — два различных процесса, которые играют ключевые роли в обеспечении безопасности ваших систем. Несмотря на то, что они часто упоминаются вместе, их цели и методы кардинально различаются.
Непонимание разницы между аутентификацией и авторизацией может привести к серьезным уязвимостям в системе безопасности. Например, сильная аутентификация без соответствующей авторизации может позволить злоумышленникам получить доступ к конфиденциальным данным или функциям, к которым они не должны иметь доступ. Аналогично, даже при правильной авторизации, недостаточная аутентификация может оставить систему открытой для атак. Понимание и правильное внедрение аутентификации и авторизации помогает защитить ваши системы и данные от несанкционированного доступа, минимизировать риски утечек информации и повысить общую безопасность. Эти процессы необходимы для создания надежных и защищенных приложений, где каждая составляющая выполняет свою важную роль.
Таким образом, разница между аутентификацией и авторизацией — это не просто теоретический вопрос, а важный аспект, который влияет на безопасность и эффективность ваших решений. Осознание и правильное использование этих процессов помогает создавать более защищенные системы, отвечающие современным требованиям безопасности.