How it works
The _ss parameter
_ss is base64-encoded JSON with two keys:
p- The
tx_part of the query string, e.g.solr tx_.solr%5Bq%5D=foo&tx_ solr%5Bpage%5D=2 s- A token: the first 12 bytes of
HMAC-, base64url-encoded (16 characters).SHA256 (encryption Key, "solr- shield")
The token is stateless and does not expire, so filter and pagination links
keep working for as long as the TYPO3 encryption stays the same.
Rotating the encryption invalidates every link that is already out
there, including links indexed by search engines.
Links
Two PSR-14 listeners rewrite generated URLs that contain tx_
parameters:
AfterUri Is Processed Event Listener - EXT:solr's
Search: facets, pagination and sorting.Uri Builder AfterLink Is Generated Event Listener - Every other
typolink. Links that still contain EXT:solr's() ###tx_placeholders are link templates that EXT:solr fills in later; they are left to the first listener.solr:…###
Other query parameters stay as they are:
Before: /search?L=1&tx_solr[q]=foo&tx_solr[filter][0]=type:pages
After: /search?L=1&_ss=eyJwIjoidHhfc29sciU1QnElNUQ9Zm9v…
Forms
The middleware maikschneider/ rewrites HTML responses.
It renames every name="tx_ attribute to name="_ and adds a
hidden _ss field with an empty payload to each form that contains such a
field. Submitting the form sends _s plus _ss, so the search form
works without JavaScript.
Range facets
EXT:solr's date and numeric range facets build their URL in the browser:
facet_ and facet_
replace the ___ and ___ placeholders of a URL template
and assign the result to window.. With URI obfuscation, the
template's tx_ parameters sit inside _ss, where these scripts
cannot find the placeholders, and the navigation bypasses solr-.
The middleware maikschneider/ therefore points every
<script> tag that loads EXT:solr's copy of these files to patched copies
in EXT:, one set for
EXT:solr 13 and one for EXT:solr 14. The patched scripts fill the range into
the _ss payload and follow the URL through a link click, which
solr- signs like any other link. It does not matter how the
stock scripts are included, for example through EXT:solr's example site sets
or your own TypoScript.
Incoming requests
The middleware maikschneider/ runs after
typo3/ and before
typo3/:
| Request | Result |
|---|---|
_s fields | Renamed back to tx_ |
Valid _ss | Payload decoded into the tx_ query parameters, _ss
removed |
tx_ parameters without _ss, or an invalid _ss | Rejected (see solrShield.uriObfuscation.rejectAction) |
Suggest request (type=7384) without _ss | Rejected |
| No Solr parameters | Passed through |
Bot detection
With solrShield.botDetection.enabled, the site set includes
EXT: in the page
footer. The script counts mouse, touch, scroll and key events and, right
before a Solr form is submitted or a link carrying _ss is followed, adds
a base64-encoded JSON payload as _solr_:
{
"elapsed": 12, "webdriver": false,
"screenWidth": 1920, "screenHeight": 1080,
"viewportWidth": 1280, "viewportHeight": 800,
"mouseMoveCount": 30, "touchCount": 0,
"scrollCount": 4, "keyCount": 6,
"ts": 1760000000000
}
The middleware scores every request that carries _ss, except autocomplete
requests, and removes _solr_ before TYPO3 resolves the page:
- Rejected outright:
webdriveris set, or the screen is 800×600, the default of many headless browsers. - Otherwise ten checks are counted: the two above, at least solrShield.botDetection.minFormTimeout seconds since page load, mouse or touch activity (see solrShield.botDetection.requireInteraction), scrolling, key presses, a viewport width and height, less than an hour since page load, and a timestamp within ten minutes of the server time. At least solrShield.botDetection.securityLevel of them must pass.
A missing or failing payload is rejected like an unsigned request (see solrShield.uriObfuscation.rejectAction).