Refactoring a Currency Converter: Secure API Keys and Universal Conversions
Introduction
The ConversorDeMonedas project began as a straightforward Java application for currency conversion. While functional, it faced common challenges associated with rapid development: a hardcoded API key directly embedded in the source code, and a rigid design that limited conversions to specific pairs, such as USD to others. These limitations introduced security vulnerabilities and hindered the application's extensibility.
The Problem with Monolithic Design and Exposed Secrets
Hardcoding sensitive information like API keys is a significant security risk. When committed to version control, it exposes credentials to anyone with access to the repository, potentially leading to misuse. Furthermore, a tightly coupled design, where API calls, parsing logic, and user interaction are intertwined, makes it difficult to introduce new features, like supporting arbitrary currency pairs, or to maintain the codebase efficiently.
Modularizing for Flexibility and Security
The refactoring effort focused on addressing these issues by adopting a more modular and secure architecture. Key components were introduced to separate concerns:
ConsultaAPI.java: This class was created to encapsulate all logic related to external API interaction. It's responsible for constructing dynamic API URLs based on user input, securely loading the API key, making HTTP requests, and parsing the JSON response usingGson.GeneradorDeArchivo.java: Dedicated to data persistence, this component centralizes the logic for saving conversion history. It ensures that each conversion, along with a timestamp and relevant details, is written to a file (e.g.,tasas.txt).Main.java: The main application class was refactored to act as an orchestrator. It manages user interaction, delegates API calls toConsultaAPI, and usesGeneradorDeArchivoto persist the results. This clear separation makes theMainclass more readable and maintainable.
Implementing Secure API Key Handling
To prevent the API key from being exposed in the source code, a crucial change was to externalize it into a config.properties file. This file is then excluded from version control using .gitignore. The ConsultaAPI class is responsible for loading this key at runtime.
Here's an illustrative example of how an API key might be loaded from a config.properties file:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ApiKeyLoader {
public static String loadApiKey() {
Properties prop = new Properties();
try (FileInputStream fis = new FileInputStream("config.properties")) {
prop.load(fis);
return prop.getProperty("API_KEY");
} catch (IOException ex) {
System.err.println("Error loading API key: " + ex.getMessage());
// In a real application, handle this more robustly, e.g., throw a custom exception
return null;
}
}
}
This snippet demonstrates how ConsultaAPI can safely retrieve the API_KEY from config.properties without embedding it directly in the Java code, enhancing security and allowing for easy updates to the key without code changes.
Achieving Universal Conversion Capabilities
The refactoring enabled the ConversorDeMonedas application to support conversions between any currency pair offered by the external API. By dynamically constructing the API request URL using the base currency provided by the user (e.g., https://example.com/api/latest/{BASE_CURRENCY}), the application is no longer limited to hardcoded USD conversions. The Gson library then efficiently parses the JSON response, allowing the application to extract exchange rates for various target currencies.
Actionable Takeaways
When developing applications that interact with external services, always prioritize security and maintainability. Separate sensitive configurations into external files (e.g., config.properties) and ensure they are excluded from version control. Embrace modular design patterns to encapsulate concerns like API interaction and data persistence. This approach not only strengthens security but also makes your application more flexible, easier to extend, and simpler to maintain over time.
Generated with Gitvlg.com