<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: chien hsin Yang</title>
    <description>The latest articles on DEV Community by chien hsin Yang (@y1j2x34).</description>
    <link>https://dev.to/y1j2x34</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3241607%2Fc20d9143-13ba-42d1-b26a-1cee61accc42.jpg</url>
      <title>DEV Community: chien hsin Yang</title>
      <link>https://dev.to/y1j2x34</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/y1j2x34"/>
    <language>en</language>
    <item>
      <title>Propify: Type-Safe Configuration and Internationalization for Java Applications</title>
      <dc:creator>chien hsin Yang</dc:creator>
      <pubDate>Mon, 23 Jun 2025 10:15:25 +0000</pubDate>
      <link>https://dev.to/y1j2x34/propify-type-safe-configuration-and-internationalization-for-java-applications-5653</link>
      <guid>https://dev.to/y1j2x34/propify-type-safe-configuration-and-internationalization-for-java-applications-5653</guid>
      <description>&lt;p&gt;In the world of Java application development, managing configuration and internationalization (i18n) has always been a challenge. Developers often resort to string-based lookups that are error-prone and lack compile-time safety. What if there was a better way? Enter &lt;strong&gt;Propify&lt;/strong&gt; — a powerful, lightweight Java annotation processor that eliminates configuration errors by generating type-safe classes from your configuration files and internationalization bundles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Say goodbye to "stringly-typed" keys and runtime errors!&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Access every configuration value and message through strongly-typed Java methods, catching invalid accesses at compile time instead of runtime.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem with Traditional Configuration
&lt;/h2&gt;

&lt;p&gt;Traditional approaches to configuration in Java applications often involve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;String-based lookups&lt;/strong&gt;: &lt;code&gt;config.getString("database.url")&lt;/code&gt; - prone to typos and no IDE assistance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual type conversion&lt;/strong&gt;: &lt;code&gt;Integer.parseInt(config.getString("server.port"))&lt;/code&gt; - tedious and error-prone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No compile-time validation&lt;/strong&gt;: Errors only discovered at runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verbose boilerplate code&lt;/strong&gt;: Creating POJOs to represent configuration structures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Similarly, internationalization typically relies on string keys that can't be validated until runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Traditional approach - error-prone  &lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ResourceBundle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBundle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"greeting"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Introducing Propify
&lt;/h2&gt;

&lt;p&gt;Propify is a lightweight Java annotation processor that automatically generates type-safe classes for both configuration files (YAML, properties, INI) and internationalization bundles. It provides a clean, intuitive API that catches errors at compile time rather than runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;strong&gt;Type-Safe Configuration&lt;/strong&gt;: Access properties through generated Java methods&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Type-Safe Internationalization&lt;/strong&gt;: Strongly-typed resource bundles with ICU4J formatting&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Compile-Time Validation&lt;/strong&gt;: Catch errors during build, not at runtime&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Nested Properties Support&lt;/strong&gt;: Hierarchical configuration with dot notation&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Custom Lookups&lt;/strong&gt;: Inject dynamic values from environment variables or custom sources&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Zero Runtime Overhead&lt;/strong&gt;: All code generated at compile time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Propify Works
&lt;/h2&gt;

&lt;p&gt;Propify uses Java's annotation processing system to generate code during compilation. Here's the basic workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Annotate&lt;/strong&gt; an interface or class with &lt;code&gt;@Propify&lt;/code&gt; or &lt;code&gt;@I18n&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile&lt;/strong&gt; your code — Propify reads your configuration files and generates type-safe classes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; the generated classes in your application code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The magic happens at compile time — Propify scans your codebase for annotations, reads the referenced configuration files, and generates Java classes that provide type-safe access to your configuration and messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Propify
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Maven
&lt;/h4&gt;

&lt;p&gt;Add dependency and annotation processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.vgerbot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;propify&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-compiler-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.8.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;1.8&lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;target&amp;gt;&lt;/span&gt;1.8&lt;span class="nt"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;annotationProcessorPaths&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;path&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.vgerbot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;propify&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/annotationProcessorPaths&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Gradle (≥4.6)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="k"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'com.vgerbot:propify:2.0.0'&lt;/span&gt;
  &lt;span class="n"&gt;annotationProcessor&lt;/span&gt; &lt;span class="s1"&gt;'com.vgerbot:propify:2.0.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Gradle (&amp;lt;4.6)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s1"&gt;'net.ltgt.apt'&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s1"&gt;'0.21'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;compile&lt;/span&gt; &lt;span class="s1"&gt;'com.vgerbot:propify:2.0.0'&lt;/span&gt;
  &lt;span class="n"&gt;apt&lt;/span&gt;     &lt;span class="s1"&gt;'com.vgerbot:propify:2.0.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type-Safe Configuration in 3 Steps
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Create a configuration file&lt;/strong&gt; (YAML, properties, or INI):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application.yml&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdbc:mysql://localhost:3306/mydb&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Annotate an interface&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Propify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application.yml"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Use the generated class&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Type-safe configuration access&lt;/span&gt;
&lt;span class="nc"&gt;AppConfigPropify&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppConfigPropify&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getServer&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getHost&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getServer&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getPort&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dbUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDatabase&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! No more string-based lookups, no more type conversion, and no more runtime errors due to typos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type-Safe Internationalization
&lt;/h3&gt;

&lt;p&gt;Propify also makes internationalization a breeze:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create message files&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# messages.properties (default)
&lt;/span&gt;&lt;span class="py"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Welcome&lt;/span&gt;
&lt;span class="py"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Hello, {name}!&lt;/span&gt;

&lt;span class="c"&gt;# messages_zh_CN.properties
&lt;/span&gt;&lt;span class="py"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;欢迎&lt;/span&gt;
&lt;span class="py"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;你好, {name}！&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Annotate a class&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@I18n&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"messages"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defaultLocale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Messages&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Access messages&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Type-safe message formatting&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;welcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDefault&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;welcome&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDefault&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Locale-specific messages&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;chineseGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Locale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CHINESE&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"张三"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Custom Lookups for Dynamic Values
&lt;/h3&gt;

&lt;p&gt;Propify supports variable interpolation in configuration files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tempDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{env:TEMP_DIR}"&lt;/span&gt;
  &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{vault:db-secret}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can implement custom lookup providers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VaultLookup&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PropifyLookup&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getPrefix&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"vault"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Retrieve secret from vault&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;VaultClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSecret&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Propify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application.yml"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;lookups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;VaultLookup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Support for Multiple Configuration Formats
&lt;/h3&gt;

&lt;p&gt;Propify supports various configuration formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YAML&lt;/strong&gt;: For hierarchical configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Properties&lt;/strong&gt;: Traditional Java properties files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INI&lt;/strong&gt;: For simple configuration needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The format is automatically detected from the file extension, or you can specify it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Propify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"config.custom"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;mediaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application/x-java-properties"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CustomConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practical Examples
&lt;/h2&gt;

&lt;p&gt;Here are some practical examples of how to use Propify in common scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# application.yml&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8443&lt;/span&gt;
    &lt;span class="na"&gt;keystore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/path/to/keystore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Propify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"application.yml"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ServerConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nc"&gt;ServerConfigPropify&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServerConfigPropify&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;httpPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getServer&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getHttp&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getPort&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// 8080&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;keystore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getServer&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getHttps&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getKeystore&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// /path/to/keystore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment-Specific Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.yml&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://{env:DB_HOST}:{env:DB_PORT}/{env:DB_NAME}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Propify&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"app.yml"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;lookups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;EnvironmentLookup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits for Enterprise Applications
&lt;/h2&gt;

&lt;p&gt;For enterprise applications, Propify offers several key benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Bugs&lt;/strong&gt;: Catch configuration errors at compile time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Developer Experience&lt;/strong&gt;: IDE auto-completion and refactoring support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Maintainability&lt;/strong&gt;: Type-safe access makes code more readable and maintainable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: No more hardcoded secrets with custom lookup providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Internationalization&lt;/strong&gt;: Type-safe message formatting with ICU support&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Help
&lt;/h2&gt;

&lt;p&gt;If you encounter any issues or have questions about using Propify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Issues&lt;/strong&gt;: Submit a &lt;a href="https://github.com/vgerbot-libraries/propify/issues" rel="noopener noreferrer"&gt;new issue&lt;/a&gt; on the GitHub repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: Check the &lt;a href="https://github.com/vgerbot-libraries/propify/wiki" rel="noopener noreferrer"&gt;Wiki&lt;/a&gt; for detailed documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;: Browse the &lt;a href="https://github.com/vgerbot-libraries/propify/tree/main/examples" rel="noopener noreferrer"&gt;examples directory&lt;/a&gt; for sample projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Propify brings type safety to configuration and internationalization in Java applications, eliminating a whole class of runtime errors and improving developer productivity. By leveraging the power of Java's annotation processing system, it provides these benefits with zero runtime overhead.&lt;/p&gt;

&lt;p&gt;Whether you're building a small application or a large enterprise system, Propify can help you manage configuration and internationalization in a type-safe, maintainable way.&lt;/p&gt;

&lt;p&gt;Ready to try Propify? Check out the &lt;a href="https://github.com/vgerbot-libraries/propify" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; and start enjoying type-safe configuration today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;Propify builds on several excellent open-source libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/square/javapoet" rel="noopener noreferrer"&gt;JavaPoet&lt;/a&gt; — Java source file generation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/FasterXML/jackson-dataformats-text" rel="noopener noreferrer"&gt;Jackson YAML&lt;/a&gt; — YAML parsing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://commons.apache.org/proper/commons-configuration/" rel="noopener noreferrer"&gt;Apache Commons Configuration&lt;/a&gt; — Configuration management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unicode-org.github.io/icu/userguide/icu4j/" rel="noopener noreferrer"&gt;ICU4J&lt;/a&gt; — Internationalization support&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>tooling</category>
      <category>configuration</category>
      <category>i18n</category>
    </item>
    <item>
      <title>Understanding CSRF Attacks: Process, Risks, and Protection</title>
      <dc:creator>chien hsin Yang</dc:creator>
      <pubDate>Mon, 23 Jun 2025 10:06:55 +0000</pubDate>
      <link>https://dev.to/y1j2x34/understanding-csrf-attacks-process-risks-and-protection-4nma</link>
      <guid>https://dev.to/y1j2x34/understanding-csrf-attacks-process-risks-and-protection-4nma</guid>
      <description>&lt;p&gt;Cross-Site Request Forgery (CSRF) is a prevalent web security vulnerability that exploits a user's authenticated session on a trusted website to perform unauthorized actions. In this blog, we'll dive into what CSRF is, how it works, its potential impact, and effective ways to prevent it. We'll also include visual sequence diagrams created with PlantUML to illustrate both the attack and protection processes, making the concept easier to grasp.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CSRF?
&lt;/h2&gt;

&lt;p&gt;CSRF is an attack where a malicious website tricks a user's browser into sending unintended requests to a legitimate website where the user is authenticated. Since browsers automatically include cookies with requests to the target site, the legitimate website may execute the request, assuming it came from the user. This can lead to serious consequences, such as unauthorized fund transfers, password changes, or data deletion.&lt;/p&gt;

&lt;p&gt;The attack relies on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user being logged into the target site (e.g., &lt;code&gt;A.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The target site trusting cookies for authentication without additional verification.&lt;/li&gt;
&lt;li&gt;The attacker crafting a malicious request on another site (e.g., &lt;code&gt;B.com&lt;/code&gt;) that the user is lured into triggering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CSRF Attack Process
&lt;/h2&gt;

&lt;p&gt;To understand how CSRF works, let's break down the attack process using a sequence diagram. The following PlantUML diagram illustrates a typical CSRF attack where a user is tricked into performing an unauthorized action on a banking website (&lt;code&gt;A.com&lt;/code&gt;) via a malicious site (&lt;code&gt;B.com&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Attack Sequence Diagram
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-0.plantuml.com%2Fplantuml%2Fpng%2FVPF1Rjiy48JlV8g5JZOGAt7odunVGImZwQbeORlfCM38jKHO8btkqadxzAL4ABABkbVn6-tESFX0B3s7je7LPlq4IsQfzh317m6jGY6aOkVX6w4NXmWQPGxICfJUlVtvRVdo7L_9C88ao9QvSYrCIcdtq-nSUyQLYViictZk0aLO50NCytueB0FNQADMCXAy6QuX_RaeH0_CxeTb5h1K2eaW0T9gQ5m5nee4TEouv0A-VjbiuJeYni94UTJT7DdGL8nEPgU_to3FLixjJHGJ4XbdNumktd_-cj_U2UiYxqrLysAG0B7pI0CCIGmxvzEElTFRv1GCmTORjKSDnhA3PqE6ZQsWlEXtrKGU3hMXkWCRO_V0BWbEJPUZwK-FqNCxX3qxo0f5-NUxQ-JWBK77fEHhepNQr1JVLOJup3RcLNu5_qT_CNx5qNAHUd3DNbhQeS-WHQwTBh8k_UmUP60te_3Q6cRKVI1t-KT-6xIQuCdv2ZMiqqHWDrRWNpSxp8I9R5smNCnlRcwkehoGVSlHJvEjT2t9IOExyVxITiQg9cWSUfNequwS3t-EuMh9EDpsPAmA7BkpwMNjupkgm0Z3wfUQk4OwE4i8anHvjXsyKkZVm2uqsRHFyx_yur5tHwWfvfQykYFwq-c9GmyU5PeZ4ko2rIJ40reTskOt" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-0.plantuml.com%2Fplantuml%2Fpng%2FVPF1Rjiy48JlV8g5JZOGAt7odunVGImZwQbeORlfCM38jKHO8btkqadxzAL4ABABkbVn6-tESFX0B3s7je7LPlq4IsQfzh317m6jGY6aOkVX6w4NXmWQPGxICfJUlVtvRVdo7L_9C88ao9QvSYrCIcdtq-nSUyQLYViictZk0aLO50NCytueB0FNQADMCXAy6QuX_RaeH0_CxeTb5h1K2eaW0T9gQ5m5nee4TEouv0A-VjbiuJeYni94UTJT7DdGL8nEPgU_to3FLixjJHGJ4XbdNumktd_-cj_U2UiYxqrLysAG0B7pI0CCIGmxvzEElTFRv1GCmTORjKSDnhA3PqE6ZQsWlEXtrKGU3hMXkWCRO_V0BWbEJPUZwK-FqNCxX3qxo0f5-NUxQ-JWBK77fEHhepNQr1JVLOJup3RcLNu5_qT_CNx5qNAHUd3DNbhQeS-WHQwTBh8k_UmUP60te_3Q6cRKVI1t-KT-6xIQuCdv2ZMiqqHWDrRWNpSxp8I9R5smNCnlRcwkehoGVSlHJvEjT2t9IOExyVxITiQg9cWSUfNequwS3t-EuMh9EDpsPAmA7BkpwMNjupkgm0Z3wfUQk4OwE4i8anHvjXsyKkZVm2uqsRHFyx_yur5tHwWfvfQykYFwq-c9GmyU5PeZ4ko2rIJ40reTskOt" alt="CSRF Attack Sequence Diagram" width="1399" height="724"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Attack Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Logs In&lt;/strong&gt;: The user visits &lt;code&gt;A.com&lt;/code&gt; (e.g., a bank) and logs in. The server responds with a session cookie (&lt;code&gt;session_id&lt;/code&gt;), stored by the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Visits Malicious Site&lt;/strong&gt;: The user is lured to &lt;code&gt;B.com&lt;/code&gt; (e.g., via a phishing email or malicious link). &lt;code&gt;B.com&lt;/code&gt; serves a page with a hidden request, such as an auto-submitting form:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://A.com/transfer"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"amount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"to"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"attacker_account"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Browser Sends Request&lt;/strong&gt;: The browser sends the forged request to &lt;code&gt;A.com&lt;/code&gt;, automatically including the &lt;code&gt;session_id&lt;/code&gt; cookie. Since the cookie is valid, &lt;code&gt;A.com&lt;/code&gt; assumes the request is legitimate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action Executed&lt;/strong&gt;: The bank processes the transfer, and the attacker receives the funds.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Risks of CSRF
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Financial Loss&lt;/strong&gt;: Unauthorized transfers or purchases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account Compromise&lt;/strong&gt;: Password changes or account settings modifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Manipulation&lt;/strong&gt;: Deleting or altering user data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reputation Damage&lt;/strong&gt;: For websites, executing unintended actions can erode user trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preventing CSRF Attacks
&lt;/h2&gt;

&lt;p&gt;To mitigate CSRF, websites must implement defenses that ensure requests are intentional and originate from trusted sources. Common protections include CSRF tokens, SameSite cookies, and request validation. Below is a PlantUML sequence diagram showing how these measures block a CSRF attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protection Sequence Diagram
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-0.plantuml.com%2Fplantuml%2Fpng%2FVPD1Rzf048Nl_XKZJY21Gq9Ej8w2KQbwQ1lXjBrKYXPxiBUsT-ZEE6dxwxlssWIYfWSkyDxElEyDjopAIbDNi4ws6xYp99YA9WC9_cpGf1W4AXMoy8NH1WSdrga-A2CGMtfw-TtguHlkM0k2OXYjmfHg6CVAb9FHkVTC5tlTHrMvtwbX9mwY22x3RYYi6YdGEAyIP7ZIKe1_EOg2JZ2x6PPPmYfDaRaNA9D1HJbe4tX1fpqkkOIxpyazN3Y9DZ1EBMRj75Nn97XECZjzFa6PhObAxSoCp8xKWywYNx__N5ujta2YQaoSAKh4wbI-corAOmrxklTKeWaC2OBLUI5By4-1HUxqc4sz2FPasq_D7OchdiHNpLeOubVJhnt14Ww5vaAR72fjIX3oXbC4yJE2z-ySWNf0Fpke78Fut-67CAt6zr3ep27pwMnxC2nd-J3CmocyRPE0wkugybTn8LOPtgCTGOrIK1QDsYv6Dw0QeHatkrgBuz75NuJ33ew_oHWsP7FCOEidWj3n8FxRyp0JnggcnaXqEP_FfyuUAH6LbcYdOCWtCF4vAjox69zeQ6gSDUWCBukU0DdM-kWuPgTblt96r_D56sBdyOq_66_i4KxE6Ffe5dzWAWpz_5epkuRz523RxzVXkWvXrUM1ZT8LEoh-FNf4Umhb-7_hgu5THGw2OtxhA3TrzHS0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-0.plantuml.com%2Fplantuml%2Fpng%2FVPD1Rzf048Nl_XKZJY21Gq9Ej8w2KQbwQ1lXjBrKYXPxiBUsT-ZEE6dxwxlssWIYfWSkyDxElEyDjopAIbDNi4ws6xYp99YA9WC9_cpGf1W4AXMoy8NH1WSdrga-A2CGMtfw-TtguHlkM0k2OXYjmfHg6CVAb9FHkVTC5tlTHrMvtwbX9mwY22x3RYYi6YdGEAyIP7ZIKe1_EOg2JZ2x6PPPmYfDaRaNA9D1HJbe4tX1fpqkkOIxpyazN3Y9DZ1EBMRj75Nn97XECZjzFa6PhObAxSoCp8xKWywYNx__N5ujta2YQaoSAKh4wbI-corAOmrxklTKeWaC2OBLUI5By4-1HUxqc4sz2FPasq_D7OchdiHNpLeOubVJhnt14Ww5vaAR72fjIX3oXbC4yJE2z-ySWNf0Fpke78Fut-67CAt6zr3ep27pwMnxC2nd-J3CmocyRPE0wkugybTn8LOPtgCTGOrIK1QDsYv6Dw0QeHatkrgBuz75NuJ33ew_oHWsP7FCOEidWj3n8FxRyp0JnggcnaXqEP_FfyuUAH6LbcYdOCWtCF4vAjox69zeQ6gSDUWCBukU0DdM-kWuPgTblt96r_D56sBdyOq_66_i4KxE6Ffe5dzWAWpz_5epkuRz523RxzVXkWvXrUM1ZT8LEoh-FNf4Umhb-7_hgu5THGw2OtxhA3TrzHS0" alt="Protection Sequence Diagram" width="1439" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Protection Mechanisms
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CSRF Tokens&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A unique, unpredictable token is included in legitimate forms or requests (e.g., as a hidden input field):
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/transfer"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"_csrf"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"random_token_12345"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"amount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Transfer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The server validates the token for each sensitive request. Since &lt;code&gt;B.com&lt;/code&gt; cannot access or forge the token, the attack fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SameSite Cookies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting the &lt;code&gt;SameSite&lt;/code&gt; attribute to &lt;code&gt;Strict&lt;/code&gt; or &lt;code&gt;Lax&lt;/code&gt; prevents the browser from including cookies in cross-site requests:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt; Set-Cookie: session_id=xyz123; SameSite=Strict
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Strict&lt;/code&gt; blocks cookies for all cross-site requests; &lt;code&gt;Lax&lt;/code&gt; allows them for top-level navigation but not for POST requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Referer/Origin Validation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server checks the &lt;code&gt;Referer&lt;/code&gt; or &lt;code&gt;Origin&lt;/code&gt; header to ensure requests come from &lt;code&gt;A.com&lt;/code&gt;. Malicious requests from &lt;code&gt;B.com&lt;/code&gt; are rejected.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secondary Authentication&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For high-risk actions (e.g., transfers), require additional verification, such as re-entering a password or a CAPTCHA.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why CSRF Protection Matters
&lt;/h2&gt;

&lt;p&gt;Without proper safeguards, CSRF vulnerabilities can lead to significant harm, especially for websites handling sensitive data like banking, e-commerce, or social platforms. Modern web frameworks (e.g., Django, Spring, Laravel) include built-in CSRF protections, but developers must ensure they are correctly configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Developers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always Use CSRF Tokens&lt;/strong&gt;: Include tokens in forms and AJAX requests for all state-changing operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adopt SameSite Cookies&lt;/strong&gt;: Set &lt;code&gt;SameSite=Strict&lt;/code&gt; or &lt;code&gt;Lax&lt;/code&gt; for session cookies to minimize cross-site risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid GET for Sensitive Actions&lt;/strong&gt;: Use POST for operations like transfers or updates to reduce the risk of simple attacks (e.g., via &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Regularly&lt;/strong&gt;: Use tools like OWASP ZAP or Burp Suite to scan for CSRF vulnerabilities in your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educate Users&lt;/strong&gt;: Warn users about phishing risks, as CSRF often relies on social engineering to lure victims to malicious sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CSRF attacks exploit the trust between a user's browser and a legitimate website, but with proper defenses like CSRF tokens and SameSite cookies, these risks can be effectively mitigated. The sequence diagrams above illustrate both the attack and protection processes, highlighting the importance of additional verification beyond cookies. By implementing robust security measures and staying vigilant, developers can protect users from CSRF and maintain trust in their applications.&lt;/p&gt;

&lt;p&gt;If you have questions about CSRF or want to dive deeper into specific defenses, feel free to leave a comment or reach out! Stay secure!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>csrf</category>
      <category>security</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
