Рубрики
Без рубрики

Начало работы с Spring Security – Аутентификация и авторизация

В последние дни я немного читал о безопасности spring, поэтому я собираюсь поделиться некоторыми из них… С тегами java, безопасность, весна.

В последние дни я немного читал о spring security, поэтому я собираюсь поделиться некоторыми вещами, которые я узнал.

Аутентификация: подтвердите личность пользователя. Авторизация: какие разрешения есть у пользователей.

Начните с добавления зависимости безопасности Spring Boot Starter в pom.xml чтобы включить базовую аутентификацию. Создайте конечную точку в своем контроллере и попытайтесь использовать ее, будет показана форма входа, предоставленная spring security.

Взгляните на консоль, когда вы запустите приложение, вы должны увидеть автоматически сгенерированный пароль, имя пользователя по умолчанию “пользователь”.

Мы даже можем настроить ваши собственные учетные данные пользователя в application.properties

spring.security.user.name=jhoni
spring.security.user.password=1234

Чтобы создать настраиваемый класс безопасности, нам нужно использовать @EnableWebSecurity и расширить класс с помощью @WebSecurityConfigurerAdapter, чтобы мы могли переопределить некоторые методы, предоставляемые этим классом. Spring security также принуждает youtu хэшировать ваши пароли, чтобы они не сохранялись в виде обычного текста. Для следующего примера мы можем использовать PasswordEncoder , конечно, это не следует использовать в производстве, но для этого примера подойдет. Альтернативой может быть BCryptPasswordEncoder .

Идентификация

В IntelliJ cmd+N и посмотрите на методы, которые вы можете переопределить. Мы собираемся использовать настроить метод с AuthenticationManagerBuilder Параметры. автор имеет различные методы, такие как Аутентификация jdbc , аутентификация ldap , Служба пользовательских данных … но мы будем использовать inMemoryAuthentication

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user1")
                .password("123")
                .roles("APPRENTICE")
                .and()
                .withUser("user2")
                .password("123")
                .roles("SENSEI");
    }

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

Авторизация

Здесь мы определяем, какие URL-адреса должны быть защищены, а какие нет. Теперь мы используем метод configure с параметром Http Security . Я предоставляю доступ любому пользователю, у которого есть роль СЕНСЕЯ.

@Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**").hasRole("SENSEI")
                .and().formLogin();

    }

Если мы попытаемся войти в систему с помощью пользователя 2, доступ будет предоставлен./** означает разрешить доступ к текущему уровню и любым внутренним уровням. Мы можем создавать разные конечные точки и вводить разные ограничения, как в следующем примере. Важно знать, что наиболее строгие правила должны быть вверху.

@Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/sensei").hasRole("SENSEI")
                .antMatchers("/apprentice").hasRole("APPRENTICE")
                .antMatchers("/").permitAll()
                .and().formLogin();
    }

Если вы хотите использовать разные роли, попробуйте hasAnyRole() . Мы также можем добавить фильтры, их цель – перехватывать запросы, и у каждого из них есть своя ответственность (мы добавим ее позже).

.hasAnyRole("ROLE1", "ROLE2", "ROLE3")
.addFilterBefore()
.addFilterAfter()

Служба пользовательских данных

Мы собираемся настроить Spring Security так, чтобы она зависела от службы пользовательских данных. Он в основном загружает пользовательские данные. автор имеет метод, называемый UserDetailsService() , который позволяет проводить индивидуальную аутентификацию на основе интерфейса UserDetailsService

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailService myUserDetailService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailService);
    }

Давайте создадим наш собственный класс Userdetailsservice и UserDetail. В MyUserDetailService мы переопределяем loadUserByUsername метод, который получит имя пользователя в качестве параметра и передаст его в наши myuserdetails .

@Service
public class MyUserDetailService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return new MyUserDetails(username);
    }
}

Когда мы реализуем интерфейс UserDetails, мы можем переопределить несколько методов. Я собираюсь создать поле имя пользователя для передачи имени пользователя при входе пользователя в систему. Остальные методы будут иметь жестко закодированные значения. getAuthorities возвращает разрешения, предоставленные пользователю, в этом случае я просто добавлю роль СЕНСЕЯ.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyUserDetails implements UserDetails {

    private String username;

    @Override
    public Collection getAuthorities() { 
        return List.of(new SimpleGrantedAuthority("ROLE_SENSEI"));
    }

    @Override
    public String getPassword() {
        return "pass";
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

Поток выглядит следующим образом:

  1. Класс веб-безопасности загружен
  2. Когда пользователь вводит имя пользователя + пароль, фильтр аутентификации перехватывает запрос, и создается объект UsernamePasswordAuthenticationToken с учетными данными запроса.
  3. loadUserByUsername получает имя пользователя.
  4. Объект myuserdetails создается с любым отправленным именем пользователя и всем остальным жестко запрограммированным (притворяющимся пользователем, который у нас есть в нашей базе данных), и он сравнивается с объектом UsernamePasswordAuthenticationToken.
  5. Если все в порядке 😃 , в противном случае ⛔️

Вместо жесткого кодирования создания моих пользовательских данных в сервисе вы можете внедрить репозиторий и получить данные пользователя из базы данных. Конечно, класс MyUserDetails придется изменить, чтобы вместо получения строки, как мы делали раньше, он получал Пользователь .

@Service
@RequiredArgsConstructor
public class MyUserDetailService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
              .orElseThrow(() -> new UsernameNotFoundException("Username does not exist"));
        return new MyUserDetails(user);
    }
}

Я собираюсь продолжить, добавив JWT в другой пост, чтобы этот не стал слишком длинным.

Оригинал: “https://dev.to/jhonifaber/getting-started-with-spring-security-authentication-and-authorization-32de”