REST API для управления постами с системой аутентификации пользователей. Реализованы базовые меры защиты от OWASP Top 10 и настроен GitHub Actions pipeline с security-сканерами (SAST и SCA).
Технологический стек: Java 21, Spring Boot 3.5.8-SNAPSHOT, PostgreSQL, JWT, Maven
POST /auth/register— регистрация нового пользователяPOST /auth/login— аутентификация пользователя (возвращает JWT токен)GET /api/data— получение списка всех пользователей. Доступно авторизованным пользователямPOST /api/posts— создание нового поста. Доступно авторизованным пользователямGET /api/posts— получение всех постов. Доступно авторизованным пользователям
Регистрация:
{
"username": "user1",
"password": "password123",
"email": "user@example.com"
}Авторизация:
{
"username": "user1",
"password": "password123"
}Создание поста:
{
"title": "Заголовок поста",
"content": "Содержимое поста минимум 10 символов"
}Доступ к /api методам есть только у авторизованных пользователей. Доступ осуществляется посредством JWT-токена. JWT-токен передается в заголовке запроса.
Регистрация
curl http://localhost:8080/auth/register \
--header 'Content-Type: application/json' \
--data '{
"username": "testuser",
"password": "password123",
"email": "test@example.com"
}'Авторизация
curl http://localhost:8080/auth/login \
--header 'Content-Type: application/json' \
--data '{
"username": "testuser",
"password": "password123"
}'Создание поста
curl http://localhost:8080/api/posts \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer $API_TOKEN' \
--data '{
"title": "My First Post",
"content": "This is the content of my first post"
}'Получение постов
curl http://localhost:8080/api/posts \
--header 'Authorization: Bearer $API_TOKEN'Используются параметризованные запросы через Spring Data JPA:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.username = :username")
Optional<User> findByUsername(@Param("username") String username);
boolean existsByUsername(String username);
}
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("SELECT p FROM Post p WHERE p.authorId = :authorId ORDER BY p.createdAt DESC")
List<Post> findByAuthorId(@Param("authorId") Long authorId);
}Пользовательские данные санитизируются с помощью OWASP Java HTML Sanitizer:
private final PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS);
public PostResponse createPost(PostRequest request) {
String sanitizedTitle = policy.sanitize(request.getTitle());
String sanitizedContent = policy.sanitize(request.getContent());
Post post = new Post();
post.setTitle(sanitizedTitle);
post.setContent(sanitizedContent);
// ...
}Демонстрация защиты от XSS:
- Приходит запрос на регистрацию/авторизацию
- AuthService хеширует пароль с BCrypt и сохраняет/сравнивает с базой
- JwtUtil выписывает JWT-токен при успешной авторизации
- Приходит запрос по /api с JWT-токеном
- JwtAuthenticationFilter достает Authorization header и ищет Bearer схему
- JwtUtil валидирует JWT-токен
Доступ к защищенному api только для аутентифицированных пользователей обеспечивается аннотацией @PreAuthorize:
@GetMapping
@PreAuthorize("isAuthenticated()")
public ResponseEntity<List<UserResponse>> getAllUsers() {
// ...
}Доступ без токена отсутствует:
Доступ по токену:
https://github.com/worthant/secure-rest-api/actions/runs/19712565117/job/56476755898



