A autenticação de usuários é uma parte essencial de aplicações modernas. Neste artigo, vamos criar uma autenticação simples com Next.js no frontend e Spring Boot no backend, utilizando JWT (JSON Web Tokens).
🛠️ Tecnologias utilizadas
- Next.js 14 (App Router)
- Spring Boot 3.x
- JWT (com biblioteca
jjwt
) - Axios (para requisições)
- BCrypt (para hash de senha)
🧪 1. Backend: Spring Boot
📦 Dependências no pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
🔐 Controlador de autenticação
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginDTO login) {
String token = authService.login(login);
return ResponseEntity.ok(Map.of("token", token));
}
}
💼 DTO de login
public class LoginDTO {
private String email;
private String password;
// getters e setters
}
🔧 Serviço com autenticação
@Service
public class AuthService {
@Autowired
private UserRepository userRepository;
public String login(LoginDTO login) {
User user = userRepository.findByEmail(login.getEmail())
.orElseThrow(() -> new RuntimeException("Usuário não encontrado"));
if (!new BCryptPasswordEncoder().matches(login.getPassword(), user.getPassword())) {
throw new RuntimeException("Senha inválida");
}
return Jwts.builder()
.setSubject(user.getEmail())
.signWith(SignatureAlgorithm.HS256, "segredo123")
.compact();
}
}
🌐 2. Frontend: Next.js
📦 Instalar dependências
npm install axios js-cookie
📁 lib/api.ts
import axios from 'axios';
export const api = axios.create({
baseURL: 'http://localhost:8080',
});
🧠 Hook de autenticação
'use client';
import { useState } from 'react';
import { api } from '@/lib/api';
import Cookies from 'js-cookie';
export default function useAuth() {
const [loading, setLoading] = useState(false);
async function login(email: string, password: string) {
setLoading(true);
try {
const res = await api.post('/auth/login', { email, password });
Cookies.set('token', res.data.token);
} finally {
setLoading(false);
}
}
return { login, loading };
}
💻 Tela de login (app/login/page.tsx
)
'use client';
import { useState } from 'react';
import useAuth from '@/hooks/useAuth';
export default function LoginPage() {
const { login, loading } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
await login(email, password);
alert('Login realizado!');
};
return (
<form onSubmit={handleLogin} className="max-w-md mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Login</h1>
<input
type="email"
placeholder="Email"
className="border p-2 w-full mb-2"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Senha"
className="border p-2 w-full mb-2"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button disabled={loading} type="submit" className="bg-blue-500 text-white px-4 py-2">
{loading ? 'Entrando...' : 'Entrar'}
</button>
</form>
);
}
✅ Considerações finais
- Use Cookies HTTPOnly para produção com segurança.
- Para rotas protegidas no Next.js, valide o JWT no servidor (middleware).
- Na Spring Boot, você pode proteger endpoints com
JwtFilter
eSecurityConfig
.
Se você quiser evoluir, pode adicionar:
- Registro de usuários
- Refresh tokens
- Autorização por papéis