PHPackages                             maikschneider/solr-shield - 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. maikschneider/solr-shield

ActiveTypo3-cms-extension[Security](/categories/security)

maikschneider/solr-shield
=========================

TYPO3 extension that protects the Apache Solr search endpoint from bots and crawlers via URI obfuscation and bot detection.

00PHPCI passing

Since Jun 11Pushed 1mo agoCompare

[ Source](https://github.com/maikschneider/solr-shield)[ Packagist](https://packagist.org/packages/maikschneider/solr-shield)[ RSS](/packages/maikschneider-solr-shield/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

Solr Shield
===========

[](#solr-shield)

[![License: GPL v2](https://camo.githubusercontent.com/77e900ae34f8da9ccccc42662fce61a94ab07ddbfe3f7d066178e824f3673dbd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c25323076322d626c75652e737667)](LICENSE.md)[![TYPO3 13](https://camo.githubusercontent.com/ff624ed071afbc7085dcd4f99f2358379f8284ba14ae6891eab075f69c55929f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31332e342d6f72616e67652e737667)](https://get.typo3.org/version/13)

TYPO3 extension that protects the [Apache Solr](https://extensions.typo3.org/extension/solr) search endpoint from bots and crawlers that enumerate search parameters (`tx_solr[filter][…]`, `tx_solr[q]`, the suggest/autocomplete endpoint) to generate thousands of unique, uncacheable requests.

**URI Obfuscation** — `tx_solr` parameters never appear in URLs or HTML form fields; every Solr request must carry a single server-signed `_ss` token. This layer is server-side, requires no JavaScript, and needs no changes to your existing Solr templates.

> **Bot detection (JavaScript) is not part of `main`.** A second, behavioural bot-detection layer is under development on the [`feature/js-bot-detection`](../../tree/feature/js-bot-detection) branch. The server-side validator (`BotDetectionService`) ships on `main` but is **disabled by default** because it depends on that client-side layer. Until the branch lands, leave `solrShield.botDetection.enabled` off.

---

Requirements
------------

[](#requirements)

DependencyVersionPHP`^8.2`TYPO3 CMS`^13.4 || ^14.0`apache-solr-for-typo3/solr`^12.0 || ^13.0`---

Installation
------------

[](#installation)

```
composer require maikschneider/solr-shield
```

Then add the **Solr Shield** site set to your site configuration (TYPO3 backend → *Site Management → Sites → \[your site\] → Sets*), or declare it as a dependency in your sitepackage's set:

```
# packages/your-sitepackage/Configuration/Sets/YourSet/config.yaml
dependencies:
  - maikschneider/solr-shield
```

Flush all caches after installation.

---

Configuration
-------------

[](#configuration)

Settings are configured per site under *Site Management → Sites → \[your site\] → Solr Shield*. All settings ship with sensible defaults.

### URI Obfuscation

[](#uri-obfuscation)

SettingTypeDefaultDescription`solrShield.uriObfuscation.enabled`bool`true`Enable/disable the obfuscation layer`solrShield.uriObfuscation.rejectAction`string`redirect`What to do with an unsigned direct `tx_solr` request: `redirect` (back to the referer) or `403`### Bot Detection

[](#bot-detection)

Bot-detection settings exist but default to **disabled** on `main` (the client-side layer they depend on lives on the [`feature/js-bot-detection`](../../tree/feature/js-bot-detection) branch). `solrShield.botDetection.enabled` defaults to `false`; the remaining keys (`minFormTimeout`, `securityLevel`, `requireInteraction`) only take effect once it is enabled together with the JavaScript layer.

You can also override the obfuscation settings in `config/sites//settings.yaml`:

```
solrShield:
  uriObfuscation:
    enabled: true
    rejectAction: redirect
```

---

How It Works
------------

[](#how-it-works)

### Protection 1 — URI Obfuscation

[](#protection-1--uri-obfuscation)

**Goal:** make `tx_solr[…]` parameters invisible in both URLs and HTML so bots cannot enumerate parameter combinations.

#### Token mechanism

[](#token-mechanism)

`TokenService` derives a compact token: the first 12 bytes of `HMAC-SHA256(encryptionKey, "solr-shield")`, base64url-encoded — **16 characters**. Tokens are **stateless and do not expire**; they remain valid as long as the TYPO3 `encryptionKey` is unchanged. This is intentional — filter and pagination links are permanent and must not rot over time.

The signed payload carried on every request is a single `_ss` parameter:

```
_ss = base64( {"p": "", "s": ""} )

```

#### Filter / pagination / typolink URLs (server-side)

[](#filter--pagination--typolink-urls-server-side)

Two PSR-14 event listeners encode any URL that carries `tx_solr` parameters into the `_ss` payload:

- **`AfterUriIsProcessedEventListener`** — hooks Solr's `SearchUriBuilder` (`AfterUriIsProcessedEvent`) for facet, pagination and sorting links.
- **`AfterLinkIsGeneratedEventListener`** — hooks `typolink()` (`AfterLinkIsGeneratedEvent`) for any other generated Solr link. It deliberately skips Solr routing *template* links that still contain `###tx_solr:…###` placeholders, leaving those to the listener above.

```
Before: /search?tx_solr[q]=foo&tx_solr[filter][0]=type:pages&tx_solr[page]=2
After:  /search?_ss=eyJwIjoidHhfc29sciU1QnElNUQ9…

```

#### Search form (server-side, no JavaScript required)

[](#search-form-server-side-no-javascript-required)

`HtmlOutputObfuscationMiddleware` rewrites the rendered HTML response:

1. Replaces every `name="tx_solr[` attribute with `name="_s[`.
2. Injects a hidden `` carrying a signed empty-payload token into each form that now contains `_s[…]` fields.

On submission `SolrShieldMiddleware` remaps `_s[…]` back to `tx_solr[…]` and validates the `_ss` token — so the search form works **without any client-side JavaScript**.

#### Middleware validation (inbound)

[](#middleware-validation-inbound)

`SolrShieldMiddleware` runs on every frontend request, positioned after site resolution (`typo3/cms-frontend/site`) and before the request-token middleware:

RequestAction`_s[…]` fields presentRemap to `tx_solr[…]`Signed `_ss` presentValidate token → base64-decode → `parse_str` → inject `tx_solr` params → strip `_ss`Direct `tx_solr` params without `_ss`Reject (redirect / 403)Suggest request (pageType `7384`) without `_ss`RejectNo Solr params, or obfuscation disabledPass through unchanged### Protection 2 — Bot Detection (in development)

[](#protection-2--bot-detection-in-development)

A second, optional layer scores behavioural signals (elapsed time, mouse/scroll/key/touch interaction, `navigator.webdriver`, screen/viewport dimensions) to reject headless and scripted clients. The server-side validator (`BotDetectionService`) ships on `main`, but the client-side JavaScript that collects the signals — and the TypoScript that wires it up — lives on the [`feature/js-bot-detection`](../../tree/feature/js-bot-detection) branch and is **not yet operational**.

Bot detection therefore defaults to **off** on `main`. Enabling it without the client-side layer would reject every form submission. Track or contribute to the work on the feature branch.

---

File Structure
--------------

[](#file-structure)

```
solr-shield/
├── Classes/
│   ├── EventListener/
│   │   ├── AfterLinkIsGeneratedEventListener.php   # Encodes typolink() Solr URLs
│   │   └── AfterUriIsProcessedEventListener.php    # Encodes Solr SearchUriBuilder URLs
│   ├── Middleware/
│   │   ├── HtmlOutputObfuscationMiddleware.php      # Renames tx_solr[ → _s[ in HTML, injects _ss
│   │   └── SolrShieldMiddleware.php                 # Validates & decodes incoming requests
│   └── Service/
│       ├── TokenService.php                         # HMAC token generation & validation
│       └── BotDetectionService.php                  # Bot-detection payload validation
├── Configuration/
│   ├── RequestMiddlewares.php                       # PSR-15 middleware registration
│   ├── Services.yaml                                # DI + event-listener registration
│   ├── Sets/SolrShield/                             # Site set: config, settings, setup
│   └── TypoScript/setup.typoscript                  # (JS wiring lives on the feature branch)
├── Resources/
│   └── Private/Language/locallang.xlf
├── composer.json
├── ext_emconf.php
└── ext_localconf.php

```

---

Development
-----------

[](#development)

This repository uses Composer-based quality tooling. After `composer install`:

```
composer ci:sca   # run all static analysis (cs-fixer, phpstan, rector, lint, editorconfig, yaml/typoscript, translations)
composer fix      # auto-fix: cs-fixer, rector, editorconfig, composer normalize
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for details.

---

License
-------

[](#license)

[GPL-2.0-or-later](LICENSE.md) — Maik Schneider.

###  Health Score

19

—

LowBetter than 9% of packages

Maintenance60

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/04b105eb2ade5d364c2ae93a9a012d591594eaa3ad54d252db70856d1c293d5d?d=identicon)[m.schneider](/maintainers/m.schneider)

---

Top Contributors

[![maikschneider](https://avatars.githubusercontent.com/u/696865?v=4)](https://github.com/maikschneider "maikschneider (9 commits)")

### Embed Badge

![Health badge](/badges/maikschneider-solr-shield/health.svg)

```
[![Health](https://phpackages.com/badges/maikschneider-solr-shield/health.svg)](https://phpackages.com/packages/maikschneider-solr-shield)
```

###  Alternatives

[mews/purifier

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

2.0k18.7M144](/packages/mews-purifier)[paragonie/ecc

PHP Elliptic Curve Cryptography library

24820.0k41](/packages/paragonie-ecc)

PHPackages © 2026

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