PHPackages                             phpgt/csrf - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. phpgt/csrf

ActiveLibrary[Security](/categories/security)

phpgt/csrf
==========

Automatic protection from Cross-Site Request Forgery.

v1.9.1(2mo ago)78.2k↑40.9%8[2 PRs](https://github.com/PhpGt/Csrf/pulls)2MITPHPPHP &gt;=8.1CI passing

Since Feb 21Pushed 2d ago2 watchersCompare

[ Source](https://github.com/PhpGt/Csrf)[ Packagist](https://packagist.org/packages/phpgt/csrf)[ GitHub Sponsors](https://github.com/sponsors/phpgt)[ RSS](/packages/phpgt-csrf/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (11)Versions (27)Used By (2)

Automatic protection from Cross-Site Request Forgery.
=====================================================

[](#automatic-protection-from-cross-site-request-forgery)

This library handles [CSRF protection](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) automatically for you, including generating tokens, injecting them into all forms in the page and then verifying that a valid token is present whenever a POST request is received.

---

[ ![Build status](https://camo.githubusercontent.com/f4235341b2abea03fb022b18418d95063ab794730ad1c47752cf3fe7625ffca8/68747470733a2f2f62616467652e7374617475732e7068702e67742f637372662d6275696c642e737667)](https://github.com/PhpGt/Csrf/actions)[ ![Code quality](https://camo.githubusercontent.com/49c6788b8ee10604b0c434010850c8bda8b9227699b55222e4da128ecc102269/68747470733a2f2f62616467652e7374617475732e7068702e67742f637372662d7175616c6974792e737667)](https://app.codacy.com/gh/PhpGt/Csrf)[ ![Code coverage](https://camo.githubusercontent.com/179d7e253bbada7320d86c954d3de6e2f6d98c61936e048965f26608ffe8125f/68747470733a2f2f62616467652e7374617475732e7068702e67742f637372662d636f7665726167652e737667)](https://app.codecov.io/gh/PhpGt/Csrf)[ ![Current version](https://camo.githubusercontent.com/9ab7251a2a1fc2df40cf562e978194d6d9386fd5834541a0716c0424ef3fe98e/68747470733a2f2f62616467652e7374617475732e7068702e67742f637372662d76657273696f6e2e737667)](https://packagist.org/packages/PhpGt/Csrf)[ ![PHP.GT/Csrf documentation](https://camo.githubusercontent.com/71b449b6f54ec07d5879865a739dc0ac2da0b5826e7e4c076ec9836dc12bb18f/68747470733a2f2f62616467652e7374617475732e7068702e67742f637372662d646f63732e737667)](http://www.php.gt/csrf)Usage: Protection in Three Steps
--------------------------------

[](#usage-protection-in-three-steps)

The CSRF library does two things:

- Injects CSRF tokens into `form`s
- Verifies `POST` requests to make sure they contain a valid token

Each is just a single method call, but you need to set up first.

### Step 1: Set up

[](#step-1-set-up)

Start by creating the TokenStore. There are currently two implementations — the `ArrayTokenStore` and `SessionTokenStore`. The `ArrayTokenStore` is the most basic and does not persist in any way, but can be extended into custom integrations. The `SessionTokenStore` is an inbuilt implementation that persists tokens between requests, so that tokens generated for one page request can be checked on another. The easiest way to add CSRF protection is to use the Session:

```
use GT\Csrf\SessionTokenStore;

// $session is an object-oriented representation of $_SESSION
// that implements the Gt\Session\SessionContainer Interface.
$tokenStore = new SessionTokenStore($session);
```

### Step 2: Verify

[](#step-2-verify)

Before running any other code (especially things that could affect data), you should check to make sure that there's a valid CSRF token in place if it's needed:

```
use GT\Csrf\Exception\CsrfException;

if(this_is_a_post_request()) {
	try {
		$tokenStore->verify();
	}
	catch(CsrfException $e) {
// Stop processing this request and get out of there!
	}
}
```

If the request contains a POST and there is no valid CSRF token, a `CSRFException` will be thrown — so you should plan to catch it. Remember, if that happens, the request was fraudulent, so you shouldn't process it!

### Step 3: Inject for Next Time

[](#step-3-inject-for-next-time)

Finally, once you've finished processing your html code and it's ready to send back to the client, you should inject the CSRF tokens. If you don't, the request will fail to pass Step 2 when the page gets submitted!

```
use GT\Csrf\HTMLDocumentProtector;

// The html can come in as anything accepted by Gt\Dom\HTMLDocument - here it's a
// plain string in a variable.
$html = "...";

// Now do the processing.
$protector = new HTMLDocumentProtector($html, $tokenStore);
$protector->protect();

// Output the HTML of the document - you will see the new fields have
// been automatically injected.
echo $protector->getHTMLDocument();
```

Using tokens of a different lengths
-----------------------------------

[](#using-tokens-of-a-different-lengths)

By default, tokens are generated as ULIDs with the prefix `CSRF_`. The configured token length refers to the ULID portion, which is 32 characters long by default in this package. The full token string length is therefore the configured token length plus the length of the prefix `CSRF_`.

Special note about client-side requests
---------------------------------------

[](#special-note-about-client-side-requests)

Note that if there are several forms on your page, a unique token will be generated and injected into each form. When a form is submitted using a client-side request (XMLHTTPRequest or Fetch, a.k.a. AJAX), the response will contain a new token that must be refreshed in the page ready for the next submission.

If you would prefer to have one token per page, shared across all forms, this can be configured by passing in the TOKEN\_PER\_PAGE parameter to the projectAndInject method: `$page->protectAndInject(HTMLDocumentProtector::TOKEN_PER_PAGE);`.

Storing one token per page will reduce the amount of server resources required, but concurrent client-side requests will fail, which is why one token per form is the default.

Alternatives to storing tokens on the session
---------------------------------------------

[](#alternatives-to-storing-tokens-on-the-session)

The package includes an `ArrayTokenStore`, which can be stored on the session. You can implement alternative token stores such as a RDBMS or NoSQL by subclassing `TokenStore` and implementing the abstract methods.

Proudly sponsored by
====================

[](#proudly-sponsored-by)

[JetBrains Open Source sponsorship program](https://www.jetbrains.com/community/opensource/)

[![JetBrains logo.](https://camo.githubusercontent.com/b5639e7738c6dfae9fe3f3e20175570b7376ce2577a772e09c25c2d4f14bf86e/68747470733a2f2f7265736f75726365732e6a6574627261696e732e636f6d2f73746f726167652f70726f64756374732f636f6d70616e792f6272616e642f6c6f676f732f6a6574627261696e732e737667)](https://www.jetbrains.com/community/opensource/)

###  Health Score

61

—

FairBetter than 98% of packages

Maintenance94

Actively maintained with recent releases

Popularity33

Limited adoption so far

Community23

Small or concentrated contributor base

Maturity82

Battle-tested with a long release history

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~218 days

Recently: every ~477 days

Total

18

Last Release

71d ago

Major Versions

v0.1.0 → v1.0.02017-02-28

PHP version history (5 changes)v0.0.1PHP &gt;=7.0.0

v1.1.0PHP &gt;=7.1

v1.5.0PHP &gt;=7.2

v1.7.1PHP &gt;=7.4

v1.8.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/9e42344b91ce4b91ab57875969f67a0a6a48de570a08bc65d673b06b72fd3a3f?d=identicon)[g105b](/maintainers/g105b)

---

Top Contributors

[![j4m3s](https://avatars.githubusercontent.com/u/1998995?v=4)](https://github.com/j4m3s "j4m3s (32 commits)")[![dependabot-preview[bot]](https://avatars.githubusercontent.com/in/2141?v=4)](https://github.com/dependabot-preview[bot] "dependabot-preview[bot] (28 commits)")[![dependabot-support](https://avatars.githubusercontent.com/u/112581971?v=4)](https://github.com/dependabot-support "dependabot-support (23 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![g105b](https://avatars.githubusercontent.com/u/358014?v=4)](https://github.com/g105b "g105b (5 commits)")[![FromSi](https://avatars.githubusercontent.com/u/22871855?v=4)](https://github.com/FromSi "FromSi (1 commits)")

---

Tags

automatic-protectioncsrfcsrf-protectioncsrf-protectorcsrf-tokensno-aiphp-securityphpgtsecurity

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phpgt-csrf/health.svg)

```
[![Health](https://phpackages.com/badges/phpgt-csrf/health.svg)](https://phpackages.com/packages/phpgt-csrf)
```

###  Alternatives

[mews/purifier

Laravel 5/6/7/8/9/10 HtmlPurifier Package

2.0k18.7M143](/packages/mews-purifier)[phpgt/webengine

Minimalistic, ergonomic PHP toolkit.

2722.3k](/packages/phpgt-webengine)[paragonie/ecc

PHP Elliptic Curve Cryptography library

24820.0k37](/packages/paragonie-ecc)[phpgt/domtemplate

Bind dynamic data to reusable HTML components.

187.7k4](/packages/phpgt-domtemplate)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
