Разбираем магических зверей безопасности: 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<String> 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 можно найти в данном материале.

Вот что в итоге, Карл!

Аутентификация и авторизация – два различных процесса, которые играют ключевые роли в обеспечении безопасности ваших систем. Несмотря на то, что они часто упоминаются вместе, их цели и методы кардинально различаются.

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

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


ссылка на оригинал статьи https://habr.com/ru/articles/821587/