<?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: Lee</title>
    <description>The latest articles on DEV Community by Lee (@leeqvip).</description>
    <link>https://dev.to/leeqvip</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4055867%2Fd9e04805-ea2e-4107-8b99-eb40e3512782.png</url>
      <title>DEV Community: Lee</title>
      <link>https://dev.to/leeqvip</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leeqvip"/>
    <language>en</language>
    <item>
      <title>One-Line Defense Against BOLA: Killing Data-Level if-else Hell with PHP-Casbin</title>
      <dc:creator>Lee</dc:creator>
      <pubDate>Thu, 10 Sep 2026 16:13:18 +0000</pubDate>
      <link>https://dev.to/leeqvip/one-line-defense-against-bola-killing-data-level-if-else-hell-with-php-casbin-4hi9</link>
      <guid>https://dev.to/leeqvip/one-line-defense-against-bola-killing-data-level-if-else-hell-with-php-casbin-4hi9</guid>
      <description>&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmt4pzsqfl8lfjfa0t6hw.jpeg" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmt4pzsqfl8lfjfa0t6hw.jpeg" alt=" " width="800" height="341"&gt;&lt;/a&gt;&lt;br&gt;
In web application security, Broken Object Level Authorization (BOLA, or IDOR) consistently haunts the top ranks of the OWASP API Security Top 10.&lt;/p&gt;

&lt;p&gt;To put it in plain English: Alice logs into your app, views her invoice at &lt;code&gt;/orders/1001&lt;/code&gt;, and then notices the number in her browser address bar. She casually changes &lt;code&gt;1001&lt;/code&gt; to &lt;code&gt;1002&lt;/code&gt;, hits Enter, and suddenly she is staring at Bob's private shipping address and billing details. If your API is even sloppier, she might fire off a &lt;code&gt;DELETE&lt;/code&gt; request and wipe out Charlie's data entirely.&lt;/p&gt;

&lt;p&gt;Most teams initially fight this vulnerability by littering their controllers with defensive &lt;code&gt;if-else&lt;/code&gt; checks. But as the product evolves, business code gets buried under layers of hotfixes—fix one leak here, accidentally open three new ones over there. &lt;/p&gt;

&lt;p&gt;Here is the good news: &lt;a href="https://github.com/php-casbin/php-casbin" rel="noopener noreferrer"&gt;PHP-Casbin&lt;/a&gt; natively supports passing full PHP objects directly into its enforcement engine. With a single line of code, you can shut down object-level authorization bypasses for good.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Pain of Hardcoded Ownership Checks
&lt;/h2&gt;

&lt;p&gt;Take a look at the all-too-familiar spaghetti code in controllers without a dedicated authorization engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// An everyday ownership check inside a controller&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Business rules and permission checks tangled together&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ForbiddenException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hands off someone else's order!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'archived'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BusinessException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Archived orders cannot be modified."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brute-force approach seems easy enough on day one, but it quickly turns into a maintenance nightmare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Leaks everywhere&lt;/strong&gt;: Updating an order needs an ownership check, viewing details needs one, downloading attachments needs one, canceling needs another. You end up copy-pasting the same snippet across dozens of endpoints. The moment a newcomer forgets that check on a new route, you have a critical security vulnerability in production.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Modifying rules feels like walking through a minefield&lt;/strong&gt;: The product manager suddenly asks: "Can quality assurance leads temporarily edit orders during business hours?" You now have to hunt down every single related controller and append new conditions to those &lt;code&gt;if&lt;/code&gt; statements, praying you did not miss one.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Permission clutter overshadows business logic&lt;/strong&gt;: The core purpose of your method is simply updating a few fields, yet half the code is occupied with detective work verifying who owns what.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Busting the Myth: Casbin Only Takes Strings?
&lt;/h2&gt;

&lt;p&gt;Many developers who have dabbled in Casbin remember it looking something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The classic route-level interception&lt;/span&gt;
&lt;span class="nv"&gt;$enforcer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/api/orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This leaves an unfortunate misconception: people assume Casbin only accepts plain strings, works exclusively at the gateway or middleware layer, and can only answer questions like "Can this user call this route?" When it comes to "Can this user edit &lt;em&gt;this specific record&lt;/em&gt;?", many believe Casbin cannot help.&lt;/p&gt;

&lt;p&gt;That could not be further from the truth. The PERM metamodel behind Casbin is remarkably expressive. In PHP-Casbin, &lt;code&gt;enforce()&lt;/code&gt; can take real PHP objects directly. While evaluating the matcher expression, the engine dynamically reaches into the object, inspects its properties, and performs the check on the fly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule Configuration: Decoupling Policy from Code
&lt;/h2&gt;

&lt;p&gt;All you need is a concise &lt;code&gt;abac_model.conf&lt;/code&gt; file to declare your ownership rules and business constraints in one clean place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[request_definition]&lt;/span&gt;
&lt;span class="py"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sub, obj, act&lt;/span&gt;

&lt;span class="nn"&gt;[policy_definition]&lt;/span&gt;
&lt;span class="py"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sub, obj, act&lt;/span&gt;

&lt;span class="nn"&gt;[policy_effect]&lt;/span&gt;
&lt;span class="py"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;some(where (p.eft == allow))&lt;/span&gt;

&lt;span class="nn"&gt;[matchers]&lt;/span&gt;
&lt;span class="py"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;r.sub.role == "admin" || (r.sub.id == r.obj.owner_id &amp;amp;&amp;amp; r.act in ["read", "update"] &amp;amp;&amp;amp; r.obj.status != "archived")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration is brief, and the logic is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;r.sub&lt;/code&gt; represents the subject (the requester). You can pass the authenticated user object directly; the engine will automatically resolve &lt;code&gt;r.sub.id&lt;/code&gt; and &lt;code&gt;r.sub.role&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;r.obj&lt;/code&gt; represents the target resource. You pass the retrieved order model directly; the engine compares &lt;code&gt;r.obj.owner_id&lt;/code&gt; and checks &lt;code&gt;r.obj.status&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;m&lt;/code&gt; serves as the referee: system administrators get an immediate green light; regular users must satisfy two strict conditions—they must own the data, and the order must not be archived.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In the Controller: Keeping Business Logic Clean
&lt;/h2&gt;

&lt;p&gt;With the policy declared externally, your controller code suddenly becomes a breath of fresh air:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Casbin\Enforcer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Enforcer&lt;/span&gt; &lt;span class="nv"&gt;$enforcer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// One clean line: pass the user, the resource, and the action to Casbin&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$enforcer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"You do not have permission to modify this record."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Clean, uncluttered business execution&lt;/span&gt;
        &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Updated successfully'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The controller no longer cares about the intricate relationship between users, roles, and resource states. It merely hands the user and the data model over to the enforcer. If it receives &lt;code&gt;false&lt;/code&gt;, it returns a 403.&lt;/p&gt;

&lt;p&gt;If product requirements change tomorrow—say, giving support supervisors temporary edit access—you only need to adjust the matcher in your configuration file. Not a single line of your controller code needs to be touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Compatibility with Real-World PHP Objects
&lt;/h2&gt;

&lt;p&gt;You might wonder: "My project uses Laravel Eloquent with dynamic attributes via &lt;code&gt;__get()&lt;/code&gt;, and my teammate prefers strongly-typed DTOs. Can Casbin handle that?"&lt;/p&gt;

&lt;p&gt;The answer is yes. PHP-Casbin comes with adaptive introspection built in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Plain DTOs, stdClass instances, or Eloquent models all work out of the box&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;findOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The engine transparently resolves public properties, getters, and magic attributes&lt;/span&gt;
&lt;span class="nv"&gt;$enforcer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whether you pass standard PHP entities, dynamic data objects, or framework models with magic getters, the engine resolves the requested fields effortlessly. There is zero need to flatten objects into arrays or serialize them to JSON beforehand. Just pass the objects as they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;If access control stops at route-level checks, it is like a security guard who checks IDs at the building's front entrance while leaving every apartment door wide open.&lt;/p&gt;

&lt;p&gt;Stop cluttering your business logic with defensive, error-prone ownership checks. By leveraging object-level ABAC in &lt;a href="https://github.com/php-casbin/php-casbin" rel="noopener noreferrer"&gt;PHP-Casbin&lt;/a&gt;, you can extract permission rules into a clean declarative model. You will shut down BOLA vulnerabilities before they hit production, and you will save your team countless hours of frustrating bug-hunting down the road.&lt;/p&gt;

</description>
      <category>permission</category>
      <category>abac</category>
      <category>datapermission</category>
      <category>casbin</category>
    </item>
    <item>
      <title>Mastering Cryptography in Go: Introducing `go-think/openssl`</title>
      <dc:creator>Lee</dc:creator>
      <pubDate>Fri, 21 Aug 2026 04:13:30 +0000</pubDate>
      <link>https://dev.to/leeqvip/mastering-cryptography-in-go-introducing-go-thinkopenssl-18eh</link>
      <guid>https://dev.to/leeqvip/mastering-cryptography-in-go-introducing-go-thinkopenssl-18eh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Zero-Boilerplate, 100% Cross-Language Compatible Encryption for Go Developers&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Cryptography in Go has always been a tale of two worlds. &lt;/p&gt;

&lt;p&gt;On one hand, Go's standard library &lt;code&gt;crypto/*&lt;/code&gt; packages are well-crafted, secure, and fast. On the other hand, implementing everyday cryptographic workflows—like encrypting a payload with &lt;strong&gt;AES-CBC (PKCS#7)&lt;/strong&gt;, performing &lt;strong&gt;AES-ECB&lt;/strong&gt; for legacy systems, or handling &lt;strong&gt;RSA encryption for large payloads&lt;/strong&gt;—requires writing dozens of lines of repetitive boilerplate code.&lt;/p&gt;

&lt;p&gt;Even worse, subtle differences in padding schemes, IV handlings, or key truncations often lead to frustrating cross-language decryption failures when communicating with &lt;strong&gt;PHP (&lt;code&gt;openssl_encrypt&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Java (&lt;code&gt;javax.crypto&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Python (&lt;code&gt;pycryptodome&lt;/code&gt;)&lt;/strong&gt;, or &lt;strong&gt;Node.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To solve these headaches once and for all, meet &lt;a href="https://github.com/go-think/openssl" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;go-think/openssl&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; — a developer-friendly, pure Go cryptographic toolkit that brings simplicity and seamless cross-platform interoperability to Go applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Why &lt;code&gt;go-think/openssl&lt;/code&gt;?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pure Go, No CGO Dependencies&lt;/strong&gt;: Lightweight, cross-compilation friendly, and built on top of standard Go crypto primitives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Boilerplate API&lt;/strong&gt;: Do what used to take 40 lines in just 2 or 3 lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% Cross-Language Compatibility&lt;/strong&gt;: Produces identical binary ciphertext to OpenSSL, PHP, Java, Python, and Node.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Padding &amp;amp; Chunking&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Native support for &lt;strong&gt;PKCS#7 (PKCS#5)&lt;/strong&gt; and &lt;strong&gt;ZeroPadding&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic chunking&lt;/strong&gt; for RSA encryption and decryption of arbitrarily long messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batteries Included&lt;/strong&gt;: AES, DES, 3DES, RSA, MD5, SHA-1 to SHA-512, and HMAC.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 Quick Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/go-think/openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Code in Action
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Symmetric Encryption: AES (CBC, ECB &amp;amp; GCM)
&lt;/h3&gt;

&lt;p&gt;Standard Go requires manual block padding, block mode initialization, and slice slicing. With &lt;code&gt;go-think/openssl&lt;/code&gt;, it is as simple as:&lt;/p&gt;

&lt;h4&gt;
  
  
  AES-CBC with PKCS#7 Padding
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/base64"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/go-think/openssl"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Cross-Language World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 16-byte key for AES-128&lt;/span&gt;
    &lt;span class="n"&gt;iv&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 16-byte IV&lt;/span&gt;

    &lt;span class="c"&gt;// Encrypt&lt;/span&gt;
    &lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AesCBCEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PKCS7_PADDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Base64 Ciphertext:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// Decrypt&lt;/span&gt;
    &lt;span class="n"&gt;plainText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AesCBCDecrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cipherText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PKCS7_PADDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Decrypted:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plainText&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Modern AEAD: AES-GCM (Authenticated Encryption)
&lt;/h4&gt;

&lt;p&gt;For applications that require authenticated encryption with integrity checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c"&gt;// 12-byte standard nonce&lt;/span&gt;
&lt;span class="n"&gt;aad&lt;/span&gt;   &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"authenticated_header"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Additional authenticated data&lt;/span&gt;

&lt;span class="c"&gt;// Encrypt&lt;/span&gt;
&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AesGCMEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Decrypt&lt;/span&gt;
&lt;span class="n"&gt;plain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AesGCMDecrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also supports &lt;strong&gt;CFB&lt;/strong&gt;, &lt;strong&gt;OFB&lt;/strong&gt;, &lt;strong&gt;CTR&lt;/strong&gt;, as well as legacy &lt;strong&gt;DES&lt;/strong&gt; and &lt;strong&gt;3DES&lt;/strong&gt; ciphers out of the box.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Painless RSA: Key Generation, Signatures &amp;amp; Auto-Chunking
&lt;/h3&gt;

&lt;p&gt;One notorious limitation of raw RSA is that it cannot encrypt data larger than its key size minus padding overhead. Usually, developers must write chunking and buffer reassembly logic. &lt;code&gt;go-think/openssl&lt;/code&gt; handles this automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"crypto"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/go-think/openssl"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// 1. Generate a 2048-bit RSA Key Pair in PEM format&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;privBuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pubBuf&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSAGenerateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;privBuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSAGeneratePublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privBuf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pubBuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;privKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;privBuf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pubKey&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pubBuf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// 2. Encrypt arbitrary-length data (Automatic chunking under the hood)&lt;/span&gt;
    &lt;span class="n"&gt;longData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A very long message that exceeds standard RSA block size limit..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSAEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;longData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Decrypt&lt;/span&gt;
    &lt;span class="n"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSADecrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Decrypted RSA:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// 3. Digital Signatures (RSASign &amp;amp; RSAVerify)&lt;/span&gt;
    &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSASign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;longData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RSAVerify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;longData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHA256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Signature verified successfully!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;RSAEncrypt&lt;/code&gt; also seamlessly accepts X.509 &lt;code&gt;CERTIFICATE&lt;/code&gt; PEM blocks!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3. One-Liner Hashes &amp;amp; HMACs
&lt;/h3&gt;

&lt;p&gt;Stop creating &lt;code&gt;hash.Hash&lt;/code&gt; interfaces just to get a hex digest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// MD5&lt;/span&gt;
&lt;span class="n"&gt;hexMD5&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Md5ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// SHA-256&lt;/span&gt;
&lt;span class="n"&gt;hexSHA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sha256ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// HMAC-SHA256&lt;/span&gt;
&lt;span class="n"&gt;hmacStr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HmacSha256ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"secret-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌐 100% Interoperability: Go vs. PHP vs. Java
&lt;/h2&gt;

&lt;p&gt;Let's test if the ciphertext generated by Go matches other platforms bit-for-bit.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Go (&lt;code&gt;go-think/openssl&lt;/code&gt;):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;iv&lt;/span&gt;  &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AesCBCEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PKCS7_PADDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// Output: 1jdzWuniG6UMtoa3T6uNLA==&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In PHP (&lt;code&gt;openssl_encrypt&lt;/code&gt;):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$key&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$iv&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1234567890123456"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;openssl_encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'aes-128-cbc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;OPENSSL_RAW_DATA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$iv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;base64_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$encrypted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Output: 1jdzWuniG6UMtoa3T6uNLA== (Identical!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In Java (&lt;code&gt;javax.crypto&lt;/code&gt;):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AES/CBC/PKCS5Padding"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENCRYPT_MODE&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;SecretKeySpec&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="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"AES"&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;IvParameterSpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doFinal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEncoder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;encodeToString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// Output: 1jdzWuniG6UMtoa3T6uNLA== (Identical!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Summary
&lt;/h2&gt;

&lt;p&gt;If you are building Go microservices that need to interact with external APIs, legacy systems, mobile apps, or other backends without wrestling with cryptographic discrepancies, &lt;code&gt;go-think/openssl&lt;/code&gt; will save you hours of debugging.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/go-think/openssl" rel="noopener noreferrer"&gt;https://github.com/go-think/openssl&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Package Documentation&lt;/strong&gt;: &lt;a href="https://pkg.go.dev/github.com/go-think/openssl" rel="noopener noreferrer"&gt;pkg.go.dev/github.com/go-think/openssl&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License&lt;/strong&gt;: Apache 2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Give it a ⭐ on GitHub if you find it useful, and feel free to submit issues or pull requests!&lt;/p&gt;

</description>
      <category>aes</category>
      <category>gcm</category>
      <category>rsa</category>
      <category>encryption</category>
    </item>
    <item>
      <title>Yii-Permission 3.0 Released: Built for Yii 3.0</title>
      <dc:creator>Lee</dc:creator>
      <pubDate>Fri, 31 Jul 2026 02:56:27 +0000</pubDate>
      <link>https://dev.to/leeqvip/yii-permission-30-released-built-for-yii-30-2dei</link>
      <guid>https://dev.to/leeqvip/yii-permission-30-released-built-for-yii-30-2dei</guid>
      <description>&lt;p&gt;In modern web development and enterprise system architecture, a flexible and efficient access control system is the ultimate cornerstone of application security. As a powerful and high-performance open-source access control framework, &lt;strong&gt;Casbin&lt;/strong&gt; supports various access control models—including ACL, RBAC, and ABAC—and is widely adopted across multiple language ecosystems.&lt;/p&gt;

&lt;p&gt;As the official Casbin extension for the PHP Yii framework, &lt;strong&gt;&lt;code&gt;php-casbin/yii-permission&lt;/code&gt; officially launched its major v3.0.0 release on July 30, 2026.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Embracing Yii 3.0's Standalone Component Ecosystem
&lt;/h3&gt;

&lt;p&gt;The core highlight of v3.0 lies in its full adaptation to the Yii 3.0 framework architecture. As Yii 3.0 transitions toward a modernized, highly componentized, and PSR-standard-compliant design, &lt;code&gt;yii-permission&lt;/code&gt; has undergone a complete architectural redesign—from low-level design to interface integration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher Minimum Environment Requirements:&lt;/strong&gt; The package now requires &lt;strong&gt;PHP 8.2+&lt;/strong&gt;, taking full advantage of the latest type system and strong typing to boost code robustness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern DI Container Configuration:&lt;/strong&gt; Upgraded configuration management powered by &lt;code&gt;yiisoft/config&lt;/code&gt; ensures that declaring and initializing the Casbin authorization engine aligns seamlessly with Yii 3.0 native standards.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Complete Decoupling: From Traditional Components to PSR-15 Middleware
&lt;/h3&gt;

&lt;p&gt;In the Yii 2.0 era, access control was largely dependent on controller-level behaviors or Application components. Following modern PHP web architecture trends, &lt;code&gt;yii-permission 3.0&lt;/code&gt; introduces &lt;strong&gt;PSR-15 standard HTTP middleware&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;EnforcerMiddleware&lt;/code&gt;&lt;/strong&gt;: Intercepts requests directly within the HTTP pipeline to execute Casbin model-based authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RequestMiddleware&lt;/code&gt;&lt;/strong&gt;: Facilitates context preprocessing and extraction from incoming requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With PSR-15 middleware, authorization logic can be effortlessly attached to global request pipelines or specific route groups, significantly improving middleware reusability and execution efficiency.&lt;/p&gt;




&lt;h3&gt;
  
  
  Seamless Integration with Yiisoft Access Interface
&lt;/h3&gt;

&lt;p&gt;To deliver a consistent developer experience for Yii users, &lt;code&gt;yii-permission 3.0&lt;/code&gt; introduces a new &lt;code&gt;AccessChecker&lt;/code&gt; class implementing the &lt;code&gt;Yiisoft\Access\AccessCheckerInterface&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This allows developers to continue using Yii's native access-checking semantics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Easily perform permission checks in controllers or services using the unified interface&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;can&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'article.update'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'article'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Permission granted: perform update operation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, authorization decisions are driven by Casbin's high-performance engine, while the application layer stays fully aligned with Yii standards—dramatically lowering the learning curve for project migrations and secondary development.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Updates Summary
&lt;/h3&gt;

&lt;p&gt;According to the official GitHub Release notes, here is a summary of the key features and breaking changes in &lt;strong&gt;v3.0.0&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yii 3.0 Compatibility:&lt;/strong&gt; Full support for Yii 3.0's standalone component ecosystem and Dependency Injection (DI) standards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updated Requirements:&lt;/strong&gt; Requires PHP 8.2 or higher and Yii 3.0 framework packages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PSR-15 Middleware Architecture:&lt;/strong&gt; Introduced &lt;code&gt;EnforcerMiddleware&lt;/code&gt; and &lt;code&gt;RequestMiddleware&lt;/code&gt; to replace legacy controller components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native &lt;code&gt;AccessChecker&lt;/code&gt; Support:&lt;/strong&gt; Added the &lt;code&gt;AccessChecker&lt;/code&gt; class implementing &lt;code&gt;Yiisoft\Access\AccessCheckerInterface&lt;/code&gt;, seamlessly empowering &lt;code&gt;$user-&amp;gt;can()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration &amp;amp; CI Optimization:&lt;/strong&gt; Integrated &lt;code&gt;yiisoft/config&lt;/code&gt; for DI configuration management; updated GitHub Actions CI workflows, PHP testing matrices, and code coverage configurations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Recommendation &amp;amp; Upgrade Advice
&lt;/h3&gt;

&lt;p&gt;If you are building a new project with &lt;strong&gt;PHP 8.2+ and Yii 3.0&lt;/strong&gt;, or planning to upgrade an existing application to Yii 3’s modern component stack, &lt;strong&gt;&lt;code&gt;php-casbin/yii-permission&lt;/code&gt; 3.0&lt;/strong&gt; is the premier access control solution.&lt;/p&gt;

&lt;p&gt;Whether you need simple RBAC for single-tenant systems, or complex, multi-tenant ABAC (Attribute-Based Access Control) for high-concurrency environments, it provides a clean, standardized, and high-performance security layer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/php-casbin/yii-permission" rel="noopener noreferrer"&gt;https://github.com/php-casbin/yii-permission&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>yii</category>
      <category>security</category>
      <category>api</category>
    </item>
  </channel>
</rss>
