Class PetstoreConsoleBoundary
- All Implemented Interfaces:
jakarta.servlet.Filter
LoopbackBoundaryFilter applied to /console and everything under it.
On console requests the boundary pins the Host, and on console writes it also requires a same-origin
Origin, a JSON body and the per-process SynchronizerToken. An allowed console request carries
the token to the page renderer, which stamps it on <body data-juneau-csrf> for the console toolkit to send
back.
The effective method
A request is judged on the method it claims, not only on its request line. A method query parameter or
an X-Method, X-HTTP-Method-Override, X-HTTP-Method or X-Method-Override header
naming anything other than a safe method makes the request a write, whether or not the resource is configured to
honour that override. So GET /console/pets/1?method=DELETE needs the same Origin and token a real
DELETE does, and a later change to a resource's allowed method overrides cannot open a hole here.
The API's token
The /petstore API is not covered by this boundary: it sits behind its own, PetstoreApiBoundary,
which has a different token. The console's one write to the API, its photo upload
(PUT /petstore/pets/{id}/photo), carries the API's token, not this one. So on every console request it
allows, this boundary also publishes a fresh API token as a String under
PetstoreApiBoundary.TOKEN_ATTRIBUTE, for the upload form to stamp. A refused request publishes nothing.
A runner must build this boundary with the PetstoreApiBoundary instance it mounts on the API. The no-arg
constructor builds a private one that nobody mounts, so the console's uploads are then refused: visibly, and
closed rather than open.
This boundary does not mark the response no-store for the API's token: the console page shell already
does so for every page carrying the console's token. When the response is already committed, the shell drops
only its own token attributes, so on that rare path the API's token can still be emitted, possibly without
no-store. That is accepted, as PetstoreApiBoundary describes.
What is outside
The /petstore-ui app (which only reads) is covered by neither boundary. The Jetty deployment puts the
microservice admin resources behind a third boundary of their own.
The authority
The single accepted Host is the "petstore.console.authority" setting when set, else
localhost:<port> with the port the request arrived on. It is fixed on the first console request, after
the server has bound, so a runner that falls back to a random port still gets the right value. Any other
spelling of the same server (127.0.0.1, a LAN host name) is answered with 421 on console paths.
Set "petstore.console.authority" whenever the browser's Host differs from the bound port: behind a Docker
port mapping or a reverse proxy, the default answers 421. A browser leaves the port out of Host
for ports 80 and 443, so the value is then the bare host name.
The boundary expects the Origin http://<authority>, so this works for plain HTTP only. An HTTPS
deployment's console stays plain-HTTP-loopback only. The API boundary reads no forwarded headers either, and the
demo does not configure the framework boundary's CONTAINER origin source, so behind a TLS-terminating proxy
the API refuses writes too (see PetstoreApiBoundary).
Example:
In a Juneau microservice, contribute a
where apiBoundary is the PetstoreApiBoundary the runner mounts on the API.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringSetting (system property, environment, or any registered source) naming the one accepted console host and port.static final StringThe covered path: the console resource's mount point.static final StringThe servlet URL pattern the boundary is registered under. -
Constructor Summary
ConstructorsConstructorDescriptionConstructor for a console boundary with an API boundary of its own.Constructor. -
Method Summary
Modifier and TypeMethodDescriptionvoiddoFilter(jakarta.servlet.ServletRequest req, jakarta.servlet.ServletResponse res, jakarta.servlet.FilterChain chain) Applies the boundary to console requests and passes every other request straight through.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface jakarta.servlet.Filter
destroy, init
-
Field Details
-
PATH
The covered path: the console resource's mount point.- See Also:
-
URL_PATTERN
The servlet URL pattern the boundary is registered under.- See Also:
-
AUTHORITY_PROPERTY
Setting (system property, environment, or any registered source) naming the one accepted console host and port.- See Also:
-
-
Constructor Details
-
PetstoreConsoleBoundary
public PetstoreConsoleBoundary()Constructor for a console boundary with an API boundary of its own.Nothing mounts that API boundary, so the API refuses the tokens this boundary publishes. A runner that mounts
PetstoreApiBoundaryusesPetstoreConsoleBoundary(PetstoreApiBoundary)instead. -
PetstoreConsoleBoundary
Constructor.- Parameters:
api- The API boundary the runner mounts, whose tokens console pages carry. Must not benull .
-
-
Method Details
-
doFilter
public void doFilter(jakarta.servlet.ServletRequest req, jakarta.servlet.ServletResponse res, jakarta.servlet.FilterChain chain) throws IOException, jakarta.servlet.ServletException Applies the boundary to console requests and passes every other request straight through.An allowed console request also carries the API's token (see
PetstoreApiBoundary).The path check makes the boundary safe to call for every request (for example when registered under a broader pattern), not only when a container maps it to
URL_PATTERN.- Specified by:
doFilterin interfacejakarta.servlet.Filter- Throws:
IOExceptionjakarta.servlet.ServletException
-