Java Security
AdvancedJava security covers input validation, cryptographic APIs, secure coding practices, and common vulnerability prevention (OWASP Top 10).
Overview
Secure Java coding spans multiple layers: input validation (prevent injection attacks), the java.security and javax.crypto APIs (hashing, encryption, signing), secure random numbers, TLS configuration, and awareness of OWASP Top 10 vulnerabilities. Security is not optional — every Java developer should know the fundamentals.
Common Vulnerabilities and Prevention
OWASP Top 10 vulnerabilities most relevant to Java: SQL Injection (use PreparedStatement), XSS (sanitise/escape output), Deserialization (use ObjectInputFilter), Path Traversal (validate file paths), and XXE (configure XML parsers safely).
General principles: validate all input, use parameterised queries, never trust user data, apply least privilege.
// SQL INJECTION — NEVER do this
String user = request.getParameter("user");
String sql = "SELECT * FROM users WHERE name = '" + user + "'";
// user = "'; DROP TABLE users; --" → catastrophic
// SAFE — PreparedStatement
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM users WHERE name = ?");
ps.setString(1, user); // parameterised — injection impossible
// PATH TRAVERSAL — validate file paths
String filename = request.getParameter("file");
// BAD: Files.readString(Path.of("/uploads/" + filename))
// filename = "../../../etc/passwd" → reads sensitive file
// SAFE — normalise and validate
Path base = Path.of("/uploads").toRealPath();
Path requested = base.resolve(filename).normalize().toRealPath();
if (!requested.startsWith(base)) {
throw new SecurityException("Path traversal detected");
}
// DESERIALIZATION — whitelist allowed classes
ObjectInputStream ois = new ObjectInputStream(fis);
ois.setObjectInputFilter(
ObjectInputFilter.Config.createFilter(
"com.example.dto.*;java.util.*;!*")); // only allow safe classesCryptography — Hashing and Encryption
MessageDigest provides cryptographic hash functions (SHA-256, SHA-3). For password storage, use PBKDF2, bcrypt, or Argon2 — never plain SHA.
Cipher provides symmetric (AES) and asymmetric (RSA) encryption. Always use strong algorithms with proper key sizes. Never hard-code cryptographic keys.
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
// SHA-256 hash (for checksums, not passwords)
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("data".getBytes(StandardCharsets.UTF_8));
String hex = HexFormat.of().formatHex(hash);
// Password hashing — PBKDF2 (use bcrypt/Argon2 in production)
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(), salt, 310_000, 256);
byte[] hashedPassword = skf.generateSecret(spec).getEncoded();
// AES-256 symmetric encryption
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256, new SecureRandom());
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[12];
new SecureRandom().nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] encrypted = cipher.doFinal("secret data".getBytes());Secure Random and TLS
java.util.Random is NOT cryptographically secure — use java.security.SecureRandom for tokens, salts, and session IDs.
For HTTPS/TLS, use HttpClient (Java 11+) or configure SSLContext with strong TLS versions. Disable SSLv3 and TLS 1.0/1.1. Certificate pinning can prevent MITM attacks in mobile/embedded scenarios.
// INSECURE — predictable
Random random = new Random();
String token = Long.toHexString(random.nextLong()); // NEVER for security
// SECURE — cryptographically random
SecureRandom secureRandom = new SecureRandom();
byte[] tokenBytes = new byte[32]; // 256-bit token
secureRandom.nextBytes(tokenBytes);
String token = Base64.getUrlEncoder().withoutPadding()
.encodeToString(tokenBytes);
// TLS configuration — restrict protocols and ciphers
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, null, new SecureRandom());
HttpClient secureClient = HttpClient.newBuilder()
.sslContext(ctx)
.build();
// JVM flags for TLS hardening
// -Djdk.tls.disabledAlgorithms=SSLv3,TLSv1,TLSv1.1,RC4,DES,MD5withRSA
// -Dhttps.protocols=TLSv1.2,TLSv1.3
// Validate certificates (always on in default HTTPS, reminder for custom trust managers)
// NEVER use a TrustManager that accepts all certificates in productionKey Points to Remember
- Use PreparedStatement always — SQL injection is the #1 Java vulnerability.
- Validate and normalise file paths before use to prevent path traversal.
- Use PBKDF2, bcrypt, or Argon2 for passwords — never plain SHA or MD5.
- SecureRandom is the only acceptable random source for security tokens and salts.
- Never trust user input, never hard-code secrets, always apply least privilege.
Practice Java Security in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaHow do you prevent SQL injection in Java?
Why is java.util.Random insecure for generating tokens?
What hashing algorithm should you use for passwords and why not SHA-256?
What is a deserialization attack and how does ObjectInputFilter mitigate it?
What is the difference between AES-CBC and AES-GCM?
Ask Aria about Java Security
Your personal AI tutor — ask anything about this concept