google-site-verification: google61fe8ba583a51912.html
Configuration Hardening in Java: Complete Security Guide

Introduction to Configuration Hardening

Configuration hardening involves securing application configurations to minimize attack surfaces and prevent security vulnerabilities. This comprehensive guide covers security best practices for Java applications, including environment-specific configurations, security headers, encryption, and compliance standards.

Core Security Configuration

Application Properties Security

application-security.yml

# Primary security configuration spring: application: name: secure-java-app # Security: Do not expose build information build: info: enabled: false # Security: Disable autoconfiguration for sensitive components autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration # Security: Servlet configuration servlet: multipart: max-file-size: 10MB max-request-size: 10MB enabled: true # Security: Jackson configuration jackson: default-property-inclusion: non_null deserialization: fail-on-unknown-properties: true parser: allow-unquoted-control-chars: false allow-comments: false visibility: field: any getter: none setter: none creator: none # Security: JPA configuration jpa: show-sql: false properties: hibernate: format_sql: false use_sql_comments: false jdbc: lob: non_contextual_creation: true # Security: Disable automatic DDL generation hbm2ddl: auto: validate # Security: Data source configuration datasource: # Security: Use environment variables for credentials url: ${DB_URL:jdbc:h2:mem:testdb} username: ${DB_USERNAME:sa} password: ${DB_PASSWORD:} hikari: connection-timeout: 30000 maximum-pool-size: 10 minimum-idle: 2 max-lifetime: 1800000 leak-detection-threshold: 60000 # Security: Mail configuration mail: properties: mail: smtp: auth: true starttls: enable: true # Security: Cache configuration cache: type: simple cache-names: - security-tokens - rate-limits caffeine: spec: maximumSize=1000,expireAfterWrite=300s # Security: Session configuration session: store-type: none timeout: 1800 servlet: filter-order: 100 # Security: Web configuration web: resources: add-mappings: false locale-resolver: fixed # Security: Messages configuration messages: encoding: UTF-8 cache-duration: 3600 # Security: Server configuration server: # Security: Server information hiding server-header: "" # Security: Port configuration port: ${SERVER_PORT:8080} # Security: SSL/TLS configuration ssl: enabled: ${SSL_ENABLED:false} key-store: ${SSL_KEY_STORE:} key-store-password: ${SSL_KEY_STORE_PASSWORD:} key-store-type: ${SSL_KEY_STORE_TYPE:PKCS12} key-alias: ${SSL_KEY_ALIAS:} protocol: TLS enabled-protocols: TLSv1.2,TLSv1.3 ciphers: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 # Security: Servlet configuration servlet: context-path: / session: cookie: http-only: true secure: ${COOKIE_SECURE:true} max-age: 1800 same-site: strict name: SESSION encoding: charset: UTF-8 enabled: true force: true # Security: HTTP configuration http2: enabled: true compression: enabled: true mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json min-response-size: 1024 # Security: Hide server version error: include-stacktrace: never include-message: never include-binding-errors: never include-exception: false # Security: Connection timeout connection-timeout: 30000 # Security: Maximum HTTP header size max-http-header-size: 8KB # Security: Logging configuration logging: level: # Security: Reduce sensitive logging com.example.secure: INFO org.springframework.security: WARN org.springframework.web: WARN org.hibernate: WARN # Security: Disable sensitive SQL logging org.hibernate.SQL: ERROR org.hibernate.type.descriptor.sql.BasicBinder: ERROR # Security: Log file configuration file: name: /var/log/secure-app/application.log max-size: 10MB max-history: 30 total-size-cap: 1GB pattern: # Security: Avoid logging sensitive information file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %mask%msg%n" console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %mask%msg%n" # Security: Actuator endpoints configuration management: endpoints: web: exposure: # Security: Limit exposed endpoints include: health,info,metrics,prometheus exclude: env,beans,configprops,dump,heapdump,threaddump,shutdown # Security: Custom management port base-path: /management enabled-by-default: false jmx: exposure: exclude: "*" endpoint: health: enabled: true show-details: when_authorized show-components: when_authorized probes: enabled: true info: enabled: true metrics: enabled: true prometheus: enabled: true # Security: Disable sensitive endpoints env: enabled: false beans: enabled: false configprops: enabled: false dump: enabled: false heapdump: enabled: false threaddump: enabled: false shutdown: enabled: false # Security: Management server configuration server: port: ${MANAGEMENT_PORT:8081} address: 127.0.0.1 ssl: enabled: true # Security: Custom application security configuration app: security: # Security: JWT configuration jwt: secret: ${JWT_SECRET:} expiration: 3600 issuer: secure-java-app audience: secure-users # Security: CORS configuration cors: allowed-origins: ${ALLOWED_ORIGINS:https://localhost:3000,https://example.com} allowed-methods: GET,POST,PUT,DELETE,OPTIONS allowed-headers: Authorization,Content-Type,X-Requested-With allow-credentials: true max-age: 3600 # Security: Rate limiting rate-limit: enabled: true requests-per-minute: 100 burst-capacity: 20 # Security: Password policy password: min-length: 12 require-uppercase: true require-lowercase: true require-digits: true require-special-chars: true max-age-days: 90 history-size: 5 # Security: Session management session: max-sessions-per-user: 1 prevent-session-fixation: true # Security: Encryption configuration encryption: algorithm: AES/GCM/NoPadding key-size: 256 iv-size: 96 salt-size: 128 # Security: Database encryption encryption: enabled: true algorithm: AES key: ${ENCRYPTION_KEY:} salt: ${ENCRYPTION_SALT:}

Environment-Specific Configurations

application-development.yml

# Development environment configuration spring: config: activate: on-profile: development # Security: Development-specific relaxations security: require-ssl: false # Security: Development database datasource: url: jdbc:h2:mem:devdb username: devuser password: devpass hikari: maximum-pool-size: 5 # Security: Development logging jackson: serialization: indent-output: true jpa: show-sql: true properties: hibernate: format_sql: true hbm2ddl: auto: create-drop # Security: Development server server: ssl: enabled: false servlet: session: cookie: secure: false # Security: Development logging logging: level: com.example.secure: DEBUG org.springframework.security: DEBUG org.hibernate.SQL: DEBUG org.hibernate.type.descriptor.sql.BasicBinder: TRACE # Security: Development endpoints management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always env: enabled: true beans: enabled: true app: security: rate-limit: enabled: false

application-production.yml

# Production environment configuration spring: config: activate: on-profile: production # Security: Production database datasource: url: ${DB_URL} username: ${DB_USERNAME} password: ${DB_PASSWORD} hikari: maximum-pool-size: 20 minimum-idle: 5 leak-detection-threshold: 120000 # Security: Production JPA jpa: properties: hibernate: hbm2ddl: auto: validate jdbc: batch_size: 50 order_inserts: true order_updates: true # Security: Production cache cache: type: redis redis: time-to-live: 3600s cache-null-values: false # Security: Production server server: ssl: enabled: true key-store: ${SSL_KEY_STORE} key-store-password: ${SSL_KEY_STORE_PASSWORD} servlet: session: timeout: 1800 cookie: secure: true same-site: strict # Security: Production logging logging: level: com.example.secure: INFO org.springframework: WARN org.hibernate: ERROR file: name: /var/log/secure-app/production.log # Security: Production management management: endpoints: web: exposure: include: health,info,metrics jmx: enabled: false endpoint: health: show-details: never app: security: rate-limit: enabled: true requests-per-minute: 60 burst-capacity: 10 session: max-sessions-per-user: 1

Security Configuration Classes

Main Security Configuration

package com.example.secure.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.boot.actuate.health.HealthEndpoint; import org.springframework.boot.actuate.info.InfoEndpoint; import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.Arrays; import java.util.List; /** * Main security configuration with comprehensive hardening */ @Configuration @EnableWebSecurity @EnableMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true ) public class SecurityConfig { @Value("${app.security.cors.allowed-origins}") private String[] allowedOrigins; @Value("${app.security.cors.allowed-methods}") private String[] allowedMethods; @Value("${app.security.cors.allowed-headers}") private String[] allowedHeaders; @Value("${app.security.cors.allow-credentials}") private boolean allowCredentials; @Value("${app.security.cors.max-age}") private long maxAge; @Autowired private JwtAuthenticationFilter jwtAuthenticationFilter; @Autowired private SecurityProperties securityProperties; /** * Password encoder with secure configuration */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); // High cost factor for better security } /** * Authentication manager */ @Bean public AuthenticationManager authenticationManager( AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } /** * Security filter chain with comprehensive hardening */ @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // Disable CSRF for stateless API (handled by JWT) .csrf(csrf -> csrf.disable()) // CORS configuration .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Session management - stateless .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) // Authorization rules .authorizeHttpRequests(authz -> authz // Public endpoints .requestMatchers( "/api/auth/login", "/api/auth/register", "/api/public/**", "/error" ).permitAll() // Actuator endpoints with role-based access .requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll() .requestMatchers(EndpointRequest.to(InfoEndpoint.class)).permitAll() .requestMatchers(EndpointRequest.to(PrometheusScrapeEndpoint.class)).hasRole("MONITORING") // All other endpoints require authentication .anyRequest().authenticated() ) // Security headers .headers(headers -> headers // Content Security Policy .contentSecurityPolicy(csp -> csp .policyDirectives("default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src 'self'; object-src 'none'; child-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; manifest-src 'self'") ) // HTTP Strict Transport Security .httpStrictTransportSecurity(hsts -> hsts .includeSubDomains(true) .preload(true) .maxAgeInSeconds(31536000) // 1 year ) // Frame options .frameOptions(frame -> frame .deny() ) // XSS Protection .xssProtection(xss -> xss .headerValue(org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK) ) // Content Type options .contentTypeOptions(contentType -> contentType .disable() // Spring Security enables this by default ) // Referrer Policy .referrerPolicy(referrer -> referrer .policy(org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN) ) // Permissions Policy .permissionsPolicy(permissions -> permissions .policy("geolocation=(), microphone=(), camera=(), payment=()") ) ) // JWT filter .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) // Exception handling .exceptionHandling(exception -> exception .authenticationEntryPoint(new JwtAuthenticationEntryPoint()) .accessDeniedHandler(new JwtAccessDeniedHandler()) ); return http.build(); } /** * CORS configuration source */ @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // Set allowed origins configuration.setAllowedOrigins(Arrays.asList(allowedOrigins)); // Set allowed methods configuration.setAllowedMethods(Arrays.asList(allowedMethods)); // Set allowed headers configuration.setAllowedHeaders(Arrays.asList(allowedHeaders)); // Set exposed headers configuration.setExposedHeaders(Arrays.asList( "Authorization", "X-Request-ID", "X-Rate-Limit-Remaining" )); // Set allow credentials configuration.setAllowCredentials(allowCredentials); // Set max age configuration.setMaxAge(maxAge); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", configuration); return source; } /** * Development-specific security configuration */ @Configuration @Profile("development") public static class DevelopmentSecurityConfig { @Bean public SecurityFilterChain developmentSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz -> authz // Allow access to development endpoints .requestMatchers( "/h2-console/**", "/actuator/**", "/swagger-ui/**", "/v3/api-docs/**" ).permitAll() ) // Allow H2 console in development .headers(headers -> headers .frameOptions(frame -> frame.sameOrigin()) ) .csrf(csrf -> csrf .ignoringRequestMatchers("/h2-console/**") ); return http.build(); } } }

JWT Security Configuration

package com.example.secure.config; import com.example.secure.security.JwtAuthenticationFilter; import com.example.secure.security.JwtTokenProvider; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.password.PasswordEncoder; import java.security.Key; import java.util.Base64; import javax.crypto.spec.SecretKeySpec; /** * JWT Security Configuration */ @Configuration public class JwtSecurityConfig { @Value("${app.security.jwt.secret}") private String jwtSecret; @Value("${app.security.jwt.expiration}") private long jwtExpiration; @Value("${app.security.jwt.issuer}") private String jwtIssuer; @Value("${app.security.jwt.audience}") private String jwtAudience; /** * JWT token provider */ @Bean public JwtTokenProvider jwtTokenProvider(PasswordEncoder passwordEncoder, ObjectMapper objectMapper) { Key key = new SecretKeySpec( Base64.getDecoder().decode(jwtSecret), "HmacSHA512" ); return new JwtTokenProvider( key, jwtExpiration, jwtIssuer, jwtAudience, passwordEncoder, objectMapper ); } /** * JWT authentication filter */ @Bean public JwtAuthenticationFilter jwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { return new JwtAuthenticationFilter(jwtTokenProvider); } }

Encryption Configuration

package com.example.secure.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; /** * Encryption configuration for data protection */ @Configuration public class EncryptionConfig { @Value("${app.security.encryption.algorithm:AES/GCM/NoPadding}") private String encryptionAlgorithm; @Value("${app.security.encryption.key-size:256}") private int keySize; @Value("${app.security.encryption.iv-size:96}") private int ivSize; @Value("${app.security.encryption.salt-size:128}") private int saltSize; @Value("${encryption.key:}") private String encryptionKey; @Value("${encryption.salt:}") private String encryptionSalt; /** * Encryption service for sensitive data */ @Bean public EncryptionService encryptionService() throws NoSuchAlgorithmException { SecretKey secretKey; if (encryptionKey != null && !encryptionKey.isEmpty()) { // Use configured key byte[] keyBytes = Base64.getDecoder().decode(encryptionKey); secretKey = new SecretKeySpec(keyBytes, "AES"); } else { // Generate new key (for development only) KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(keySize); secretKey = keyGenerator.generateKey(); } return new EncryptionService( secretKey, encryptionAlgorithm, ivSize, saltSize ); } /** * Secure random number generator */ @Bean public SecureRandom secureRandom() { return new SecureRandom(); } /** * Encryption service implementation */ public static class EncryptionService { private final SecretKey secretKey; private final String algorithm; private final int ivSize; private final int saltSize; private final SecureRandom secureRandom; public EncryptionService(SecretKey secretKey, String algorithm, int ivSize, int saltSize) { this.secretKey = secretKey; this.algorithm = algorithm; this.ivSize = ivSize; this.saltSize = saltSize; this.secureRandom = new SecureRandom(); } public String encrypt(String plaintext) throws Exception { byte[] iv = new byte[ivSize / 8]; secureRandom.nextBytes(iv); Cipher cipher = Cipher.getInstance(algorithm); GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec); byte[] ciphertext = cipher.doFinal(plaintext.getBytes()); byte[] encrypted = new byte[iv.length + ciphertext.length]; System.arraycopy(iv, 0, encrypted, 0, iv.length); System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length); return Base64.getEncoder().encodeToString(encrypted); } public String decrypt(String encrypted) throws Exception { byte[] decoded = Base64.getDecoder().decode(encrypted); byte[] iv = new byte[ivSize / 8]; System.arraycopy(decoded, 0, iv, 0, iv.length); Cipher cipher = Cipher.getInstance(algorithm); GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec); byte[] ciphertext = new byte[decoded.length - iv.length]; System.arraycopy(decoded, iv.length, ciphertext, 0, ciphertext.length); byte[] plaintext = cipher.doFinal(ciphertext); return new String(plaintext); } public byte[] generateSalt() { byte[] salt = new byte[saltSize / 8]; secureRandom.nextBytes(salt); return salt; } } }

Security Headers Configuration

Custom Security Headers Filter

package com.example.secure.config; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * Custom security headers configuration */ @Configuration public class SecurityHeadersConfig { /** * Custom security headers filter */ @Bean public FilterRegistrationBean<SecurityHeadersFilter> securityHeadersFilter() { FilterRegistrationBean<SecurityHeadersFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new SecurityHeadersFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; } /** * Custom security headers filter implementation */ public static class SecurityHeadersFilter implements Filter { private final Map<String, String> securityHeaders = new HashMap<>(); public SecurityHeadersFilter() { // Security headers configuration securityHeaders.put("X-Content-Type-Options", "nosniff"); securityHeaders.put("X-Frame-Options", "DENY"); securityHeaders.put("X-XSS-Protection", "1; mode=block"); securityHeaders.put("Referrer-Policy", "strict-origin-when-cross-origin"); securityHeaders.put("Permissions-Policy", "geolocation=(), microphone=(), camera=()"); securityHeaders.put("X-Permitted-Cross-Domain-Policies", "none"); securityHeaders.put("X-Download-Options", "noopen"); securityHeaders.put("X-DNS-Prefetch-Control", "off"); securityHeaders.put("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload"); // Custom headers securityHeaders.put("X-Request-ID", ""); securityHeaders.put("X-Runtime", ""); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // Add security headers securityHeaders.forEach((key, value) -> { if (!httpResponse.containsHeader(key)) { if (key.equals("X-Request-ID")) { // Generate unique request ID String requestId = java.util.UUID.randomUUID().toString(); httpResponse.setHeader(key, requestId); } else if (key.equals("X-Runtime")) { // Will be set after processing } else { httpResponse.setHeader(key, value); } } }); // Measure processing time long startTime = System.currentTimeMillis(); try { chain.doFilter(request, response); } finally { long endTime = System.currentTimeMillis(); httpResponse.setHeader("X-Runtime", String.valueOf(endTime - startTime)); } } @Override public void init(FilterConfig filterConfig) throws ServletException { // Initialization logic if needed } @Override public void destroy() { // Cleanup logic if needed } } }

Rate Limiting Configuration

package com.example.secure.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.util.concurrent.TimeUnit; /** * Rate limiting configuration */ @Configuration public class RateLimitingConfig { @Value("${app.security.rate-limit.enabled:true}") private boolean rateLimitEnabled; @Value("${app.security.rate-limit.requests-per-minute:100}") private int requestsPerMinute; @Value("${app.security.rate-limit.burst-capacity:20}") private int burstCapacity; /** * Rate limiting service */ @Bean public RateLimitingService rateLimitingService(RedisTemplate<String, Object> redisTemplate) { return new RateLimitingService( redisTemplate, rateLimitEnabled, requestsPerMinute, burstCapacity ); } /** * Redis template for rate limiting */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setEnableTransactionSupport(true); return template; } /** * Rate limiting service implementation */ public static class RateLimitingService { private final RedisTemplate<String, Object> redisTemplate; private final boolean enabled; private final int requestsPerMinute; private final int burstCapacity; public RateLimitingService(RedisTemplate<String, Object> redisTemplate, boolean enabled, int requestsPerMinute, int burstCapacity) { this.redisTemplate = redisTemplate; this.enabled = enabled; this.requestsPerMinute = requestsPerMinute; this.burstCapacity = burstCapacity; } public boolean isAllowed(String clientId, String endpoint) { if (!enabled) { return true; } String key = String.format("rate_limit:%s:%s", clientId, endpoint); long currentTime = System.currentTimeMillis(); long windowSize = TimeUnit.MINUTES.toMillis(1); // Get current count Long currentCount = redisTemplate.opsForValue().increment(key, 1); if (currentCount == 1) { // First request in this window, set expiration redisTemplate.expire(key, windowSize, TimeUnit.MILLISECONDS); } return currentCount <= requestsPerMinute; } public RateLimitInfo getRateLimitInfo(String clientId, String endpoint) { String key = String.format("rate_limit:%s:%s", clientId, endpoint); Long currentCount = redisTemplate.opsForValue().increment(key, 0); // Get without incrementing if (currentCount == null) { currentCount = 0L; } long remaining = Math.max(0, requestsPerMinute - currentCount); long resetTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(1); return new RateLimitInfo(remaining, resetTime); } } /** * Rate limit information */ public static class RateLimitInfo { private final long remaining; private final long resetTime; public RateLimitInfo(long remaining, long resetTime) { this.remaining = remaining; this.resetTime = resetTime; } public long getRemaining() { return remaining; } public long getResetTime() { return resetTime; } } }

Logging Security Configuration

Secure Logging Configuration

package com.example.secure.config; import ch.qos.logback.classic.PatternLayout; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.pattern.PatternLayoutEncoderBase; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.regex.Pattern; /** * Secure logging configuration */ @Configuration public class LoggingSecurityConfig { /** * Pattern layout with sensitive data masking */ @Bean public PatternLayoutEncoderBase<ILoggingEvent> patternLayoutEncoder() { return new SecurePatternLayoutEncoder(); } /** * Secure pattern layout that masks sensitive information */ public static class SecurePatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> { private static final Pattern SENSITIVE_PATTERNS = Pattern.compile( "(?i)(password|pwd|secret|key|token|auth|credential|ssn|credit.?card)=[^&,\\s]+", Pattern.CASE_INSENSITIVE ); @Override public void start() { PatternLayout patternLayout = new PatternLayout() { @Override public String doLayout(ILoggingEvent event) { String original = super.doLayout(event); return maskSensitiveData(original); } }; patternLayout.setContext(context); patternLayout.setPattern(getPattern()); patternLayout.setOutputPatternAsHeader(outputPatternAsHeader); patternLayout.start(); this.layout = patternLayout; super.start(); } /** * Mask sensitive data in log messages */ private String maskSensitiveData(String message) { if (message == null) { return null; } // Mask passwords, tokens, etc. String masked = SENSITIVE_PATTERNS.matcher(message) .replaceAll("$1=***"); // Mask email addresses masked = Pattern.compile("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b") .matcher(masked) .replaceAll("***@***.***"); // Mask IP addresses masked = Pattern.compile("\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b") .matcher(masked) .replaceAll("***.***.***.***"); // Mask credit card numbers masked = Pattern.compile("\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\\d{3})\\d{11})\\b") .matcher(masked) .replaceAll("****************"); return masked; } } }

Database Security Configuration

JPA Configuration with Security

```java
package com.example.secure.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**

  • JPA configuration with security enhancements
    */
    @Configuration
    @EnableJpaRepositories(
    basePackages = "com.example.secure.repository",
    entityManagerFactoryRef = "entityManagerFactory",
    transactionManagerRef = "transactionManager"
    )
    @EnableTransactionManagement
    @EnableJpaAuditing
    public class DatabaseSecurityConfig { @Autowired
    private DataSource dataSource; /**
    • Entity manager factory with security properties
      */
      @Bean
      public LocalContainerEntityManagerFactoryBean entityManagerFactory(
      EntityManagerFactoryBuilder builder) { Map properties = new HashMap<>();

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper