Как в Spring реализовать авторизацию с использованием Bearer токенов, не используя JWT?

Как создать и реализовать генерацию и хранение обычных токенов, представляющих собой набор случайных символов, связанных с пользователем и сохраненных в базе данных, без использования JWT?
  • 12 февраля 2024 г. 17:09
Ответы на вопрос 2
Для реализации авторизации с использованием Bearer токенов без JWT в Spring, вы можете следовать следующим шагам:

1. Создайте модель токена, которая будет представлять ваш токен в базе данных. Сюда входит информация о пользователе, к которому токен привязан, срок действия токена и сам токен, который может быть строкой случайных символов.

```java
import javax.persistence.*;
import java.time.Instant;

@Entity
public class AuthToken {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String token;

    @ManyToOne
    private User user; // Ваша сущность пользователя

    private Instant expiryDate;

    // Геттеры и сеттеры
}
```

2. Создайте репозиторий для взаимодействия с моделью токена и базой данных.

```java
import org.springframework.data.jpa.repository.JpaRepository;

public interface AuthTokenRepository extends JpaRepository<AuthToken, Long> {
    AuthToken findByToken(String token);
}
```

3. Генерируйте токен для пользователя, например, используя `UUID.randomUUID().toString()` или более сложный генератор. Сохраните токен в базе данных с ссылкой на пользователя и определенным сроком действия.

```java
import java.time.Instant;
import java.util.UUID;

@Service
public class TokenService {

    @Autowired
    private AuthTokenRepository authTokenRepository;

    public AuthToken createToken(User user) {
        AuthToken authToken = new AuthToken();
        authToken.setToken(UUID.randomUUID().toString());
        authToken.setUser(user);
        authToken.setExpiryDate(Instant.now().plusSeconds(3600)); // Срок действия токена, например, 1 час
        return authTokenRepository.save(authToken);
    }

    // Методы для обновления и удаления токенов
}
```

4. Создайте фильтр для обработки Bearer токенов, проверяющий в каждом запросе наличие и валидность токена. В случае успеха, установите информацию о пользователе в контексте безопасности.

```java
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class TokenAuthenticationFilter extends GenericFilterBean {

    private TokenService tokenService;

    public TokenAuthenticationFilter(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            String tokenStr = getTokenFromRequest((HttpServletRequest) request);
            if (tokenStr != null) {
                AuthToken authToken = tokenService.findByToken(tokenStr);
                if (authToken != null && authToken.getExpiryDate().isAfter(Instant.now())) {
                    // Создать Authentication и установить его в SecurityContextHolder
                    Authentication authentication = /* создайте Authentication на основе данных пользователя */
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        } catch (Exception e) {
            // Обработка ошибки
        }

        chain.doFilter(request, response);
    }
}
```

5. Настройте Spring Security, добавив ваш фильтр авторизации:

```java
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private TokenService tokenService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(new TokenAuthenticationFilter(tokenService), UsernamePasswordAuthenticationFilter.class)
            // другие настройки безопасности ...
            ;
    }
}
```

6. Дополнительно может потребоваться создать кастомную реализацию `Authentication`, если ваша схема аутентифика
В контексте Authentication , нужно смотреть в сторону ручной авторизации (автоматическая авторизация после регистрации). Там всё достаточно просто и понятно. Ну а если хочется изобрести что-то новенькое, то нужно читать документацию: https://docs.spring.io/spring-security/site/docs/4...
Похожие вопросы