Secure Coding Practices: Complete Guide

1️⃣ Introduction

Secure coding is essential for building robust and secure applications. This guide covers fundamental security practices and common vulnerabilities to avoid.

Key areas covered:

  • Input Validation
  • Authentication & Authorization
  • Data Protection
  • Error Handling
  • Security Headers
  • Best Practices

2️⃣ Input Validation

🔹 Validation Strategies

public class InputValidator {
    public boolean validateInput(String input) {
        // Whitelist validation
        return input != null && 
            input.matches("^[a-zA-Z0-9\\s-_]{1,50}$");
    }
    
    public String sanitizeHtml(String input) {
        // Use a library like OWASP Java Encoder
        return Encode.forHtml(input);
    }
    
    public boolean validateEmail(String email) {
        if (email == null || email.isEmpty()) {
            return false;
        }
        
        // Email validation pattern
        String pattern = "^[A-Za-z0-9+_.-]+@(.+)$";
        return email.matches(pattern);
    }
    
    public String sanitizeSql(String input) {
        // Use PreparedStatement instead
        throw new IllegalStateException(
            "Use PreparedStatement for SQL");
    }
}

🔹 SQL Injection Prevention

public class SecureDao {
    public User findUser(String username) {
        String sql = "SELECT * FROM users WHERE username = ?";
        
        try (PreparedStatement stmt = 
                connection.prepareStatement(sql)) {
            stmt.setString(1, username);
            ResultSet rs = stmt.executeQuery();
            return mapResultToUser(rs);
        }
    }
    
    public void updateUser(User user) {
        String sql = "UPDATE users SET email = ? " +
            "WHERE id = ?";
            
        try (PreparedStatement stmt = 
                connection.prepareStatement(sql)) {
            stmt.setString(1, user.getEmail());
            stmt.setLong(2, user.getId());
            stmt.executeUpdate();
        }
    }
}

3️⃣ Authentication & Authorization

🔹 Password Security

public class PasswordService {
    private static final int SALT_LENGTH = 16;
    private static final int ITERATIONS = 10000;
    private static final int KEY_LENGTH = 256;
    
    public String hashPassword(String password) {
        byte[] salt = generateSalt();
        byte[] hash = hashWithPbkdf2(password, salt);
        return Base64.encode(salt) + ":" + 
            Base64.encode(hash);
    }
    
    private byte[] hashWithPbkdf2(
            String password, byte[] salt) {
        KeySpec spec = new PBEKeySpec(
            password.toCharArray(),
            salt,
            ITERATIONS,
            KEY_LENGTH
        );
        
        try {
            SecretKeyFactory factory = 
                SecretKeyFactory.getInstance(
                    "PBKDF2WithHmacSHA256");
            return factory.generateSecret(spec)
                .getEncoded();
        } catch (Exception e) {
            throw new RuntimeException(
                "Error hashing password", e);
        }
    }
    
    private byte[] generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_LENGTH];
        random.nextBytes(salt);
        return salt;
    }
}

🔹 JWT Security

public class JwtService {
    private static final String SECRET_KEY = 
        System.getenv("JWT_SECRET");
    private static final long EXPIRATION = 86400000; // 24h
    
    public String generateToken(User user) {
        Date now = new Date();
        Date expiry = new Date(
            now.getTime() + EXPIRATION);
            
        return Jwts.builder()
            .setSubject(user.getUsername())
            .setIssuedAt(now)
            .setExpiration(expiry)
            .signWith(SignatureAlgorithm.HS512, 
                SECRET_KEY)
            .compact();
    }
    
    public boolean validateToken(String token) {
        try {
            Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token);
            return true;
        } catch (JwtException e) {
            return false;
        }
    }
}

4️⃣ Data Protection

🔹 Encryption

public class EncryptionService {
    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int TAG_LENGTH = 128;
    
    public byte[] encrypt(byte[] data, SecretKey key) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            byte[] iv = generateIv();
            
            GCMParameterSpec spec = 
                new GCMParameterSpec(TAG_LENGTH, iv);
            cipher.init(Cipher.ENCRYPT_MODE, key, spec);
            
            byte[] encrypted = cipher.doFinal(data);
            return combineIvAndData(iv, encrypted);
        } catch (Exception e) {
            throw new RuntimeException(
                "Encryption failed", e);
        }
    }
    
    public byte[] decrypt(byte[] data, SecretKey key) {
        try {
            byte[] iv = extractIv(data);
            byte[] encrypted = extractData(data);
            
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            GCMParameterSpec spec = 
                new GCMParameterSpec(TAG_LENGTH, iv);
                
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            return cipher.doFinal(encrypted);
        } catch (Exception e) {
            throw new RuntimeException(
                "Decryption failed", e);
        }
    }
    
    private byte[] generateIv() {
        byte[] iv = new byte[12];
        new SecureRandom().nextBytes(iv);
        return iv;
    }
}

5️⃣ Error Handling

🔹 Secure Error Handling

public class SecureErrorHandler {
    private static final Logger log = 
        LoggerFactory.getLogger(
            SecureErrorHandler.class);
            
    public ApiResponse handleError(Exception e) {
        // Log full error for debugging
        log.error("Error occurred", e);
        
        // Return safe error message to client
        if (e instanceof ValidationException) {
            return new ApiResponse(400, 
                "Invalid input provided");
        } else if (e instanceof AuthenticationException) {
            return new ApiResponse(401, 
                "Authentication required");
        } else {
            // Generic error for unknown issues
            return new ApiResponse(500, 
                "An internal error occurred");
        }
    }
    
    public void logSecurityEvent(
            String event, String username) {
        // Structured logging for security events
        log.info("Security event: {} for user: {}", 
            event, username);
    }
}

6️⃣ Q&A / Frequently Asked Questions

Key risks: (1) Injection. (2) Broken Authentication. (3) Sensitive Data Exposure. (4) XML External Entities. (5) Broken Access Control. (6) Security Misconfiguration. (7) Cross-Site Scripting. (8) Insecure Deserialization. (9) Using Components with Known Vulnerabilities. (10) Insufficient Logging & Monitoring.

Best practices: (1) Use strong encryption. (2) Hash passwords with salt. (3) Use secure key storage. (4) Implement proper access controls. (5) Regular key rotation. (6) Secure configuration storage. (7) Data masking. (8) Audit logging.

Essential headers: (1) Content-Security-Policy. (2) X-Frame-Options. (3) X-XSS-Protection. (4) X-Content-Type-Options. (5) Strict-Transport-Security. (6) Referrer-Policy. (7) Feature-Policy. (8) Cache-Control.

7️⃣ Best Practices & Pro Tips 🚀

  • Validate all inputs
  • Use prepared statements
  • Implement proper authentication
  • Enable security headers
  • Use HTTPS everywhere
  • Implement proper logging
  • Regular security updates
  • Secure configuration
  • Access control checks
  • Error handling
  • Security testing
  • Code reviews

Read Next 📖

Conclusion

Implementing secure coding practices is crucial for building robust and secure applications. By following the principles and practices outlined in this guide, you can significantly improve your application's security posture.

Remember to stay updated with security best practices and regularly review and update your security measures.