A secure REST API backend for a personal blog and project portfolio website, featuring JWT authentication, post management, and image uploading.
This Spring Boot application serves as the backend for a full stack blog platform, and provides authenticated CRUD operations for posts, image upload functionality, and secure user authentication via JWT tokens. The API is consumed by a React frontend and can be used for containerized deployment.
- π JWT Authentication: Secure token based authentication for administrative functions
- βοΈ Post Management: Full CRUD operations for blog posts and project entries
- πΌοΈ Image Uploads: File upload and serving functionality for post images/gifs
- π Pagination & Filtering: Support for paginated results with category filters (blog/projects)
- π CORS Configuration: Configured for both local development and production deployment
- πΎ Flexible Database: Support for H2, MySQL, and PostgreSQL via configuration
- π‘οΈ Security: Spring Security integration with JWT filter chain
Category | Technology |
---|---|
Language | Java |
Framework | Spring Boot |
Security | Spring Security + JWT |
Data Layer | Spring Data JPA (Hibernate) |
Database | PostgreSQL / MySQL / H2 |
Build Tool | Maven |
Authentication | JSON Web Tokens (JWT) |
blog-app/
βββ src/
β βββ java/com/example/blog/
| β βββ BlogAppAppliation.java # Main entry point; configures startup tasks & CORS
| β βββ JwtFilter.java # Security filter; validates JWT per request
| β βββ JwtUtil.java # Utility class; generate/validate/parse JWT tokens
| β βββ LoginController.java # Handles /api/auth endpoints; admin login + token issue
| β βββ Post.java # Entity model; represents a blog post (title, content, etc.)
| β βββ PostController.java # REST API for blog posts; CRUD + pagination + image upload
| β βββ PostRepository.java # JPA repository; built-in CRUD + custom queries
| β βββ puppy.java # Unused File, can be ignored. Made for fun
| β βββ SecurityConfig.java # Configures Spring Security, JWT filter, access rules
| β βββ WebConfig.java # Exposes "uploads" folder for serving images
β βββ resources/
| β βββ application.properties # App configuration (DB, JWT secret, admin credentials, etc.)
βββ pom.xml # Maven project definition
deployment/
βββ appdata/
β βββ blog_backend/
β β βββ application.properties # Production configuration
β β βββ blog-app.jar # Compiled Spring Boot JAR
β β βββ uploads/ # Persistent image storage
β βββ postgres_blog/ # PostgreSQL data volume
βββ docker-compose.yml # Container orchestration
- Java JDK: 17 or higher
- Maven: 3.8+
- Database: PostgreSQL, MySQL, or H2 (in-memory)
-
Clone the repository
git clone https://github.com/your-username/blog-backend.git cd blog-backend
-
Configure application properties
Edit
src/main/resources/application.properties
:# Server Configuration server.port=8090 # Database Configuration (PostgreSQL example) spring.datasource.url=Database URL or PORT spring.datasource.username=your_db_user spring.datasource.password=your_db_password spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect # JWT Configuration app.jwt.secret=your-256-bit-secret-key-here app.jwt.expiration=86400000 # Admin Credentials app.admin.user=admin app.admin.pass=secure_password_here # CORS Origins (comma-separated) CORS_ORIGINS=http://localhost:5173,https://your-domain.com # File Upload spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB
-
Build the application
mvn clean install
-
Run the application
mvn spring-boot:run
The API will be available at
http://localhost:8090/api
# Build JAR
mvn clean package
# Run JAR
java -jar target/blog-app-0.0.1-SNAPSHOT.jar
Method | Endpoint | Description | Auth Required |
---|---|---|---|
POST | /api/auth/login |
Admin login, returns JWT token | No |
Request Body (Login):
{
"username": "admin",
"password": "your_password"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"username": "admin"
}
}
Method | Endpoint | Description | Auth Required |
---|---|---|---|
GET | /api/posts |
Fetch paginated posts | No |
GET | /api/posts/{id} |
Fetch single post by ID | No |
POST | /api/posts |
Create new post | Yes (JWT) |
PUT | /api/posts/{id} |
Update existing post | Yes (JWT) |
DELETE | /api/posts/{id} |
Delete post | Yes (JWT) |
Query Parameters (GET /api/posts):
page
(int): Page number (default: 0)size
(int): Items per page (default: 10)type
(string): Filter by type - "blog" or "project"
Request Body (Create/Update Post):
{
"title": "My Blog Post",
"content": "<p>Rich text content here</p>",
"type": "blog",
"imageUrls": ["image1.jpg", "image2.jpg"]
}
Method | Endpoint | Description | Auth Required |
---|---|---|---|
POST | /api/posts/upload-image |
Upload image for posts | Yes (JWT) |
GET | /api/posts/uploads/{filename} |
Serve uploaded image | No |
Upload Request:
- Content-Type:
multipart/form-data
- Field name:
file
- Accepted formats: JPG, PNG, GIF
- Max size: 10MB
- Client requests login via
/api/auth/login
with credentials - Server validates credentials against configured admin user
- Server generates JWT with expiration time
- Client stores token (localStorage/sessionStorage)
- Client includes token in
Authorization: Bearer <token>
header for protected routes - JwtFilter validates token on each protected request
- Token expires after configured duration
- JWT Token Authentication: Stateless authentication with configurable expiration
- CORS Configuration: Whitelised origin control
- Request Filtering: JWT validation on protected endpoints
- SQL Injection Prevention: JPA parameterized queries
- XSS Protection: Content sanitization on frontend (DOMPurify)
All endpoints under /api/posts
(except GET requests) require a valid JWT token in the Authorization header.
-
Package the application
mvn clean package -DskipTests
-
Copy JAR to deployment directory
cp target/blog-app-0.0.1-SNAPSHOT.jar deployment/appdata/blog_backend/blog-app.jar
-
Configure production properties
Copy the previous
application.properties
into the same directory as the .jar file -
Run with Docker Compose
- Frontend: Personal Website Frontend
- Docker Setup: Home Server Configuration
- Comment system for blog posts
- Tag/category management
- Search functionality with Elasticsearch
This project is licensed under the MIT License - see the LICENSE file for details.