Skip to content

Commit 81b7791

Browse files
authored
Introduced SecurityHandler.PathMethodMapped (#13832)
* `SecurityHandler.PathMethodMapped` allows to map constraints to both path specs and HTTP methods. * Added full security documentation, documenting `SecurityHandler.PathMethodMapped` but also `SecurityHandler.PathMapped`, as well as set up of security for both Jetty Core and Jakarta. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
1 parent 35f9763 commit 81b7791

File tree

11 files changed

+1177
-45
lines changed

11 files changed

+1177
-45
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
package org.eclipse.jetty.docs.programming.security;
15+
16+
import java.security.Principal;
17+
18+
import org.eclipse.jetty.ee11.servlet.security.ConstraintMapping;
19+
import org.eclipse.jetty.ee11.servlet.security.ConstraintSecurityHandler;
20+
import org.eclipse.jetty.ee11.webapp.WebAppContext;
21+
import org.eclipse.jetty.security.Constraint;
22+
import org.eclipse.jetty.security.HashLoginService;
23+
import org.eclipse.jetty.security.SecurityHandler;
24+
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
25+
import org.eclipse.jetty.server.Handler;
26+
import org.eclipse.jetty.server.Request;
27+
import org.eclipse.jetty.server.Response;
28+
import org.eclipse.jetty.server.Server;
29+
import org.eclipse.jetty.server.handler.ContextHandler;
30+
import org.eclipse.jetty.util.Callback;
31+
import org.eclipse.jetty.util.resource.ResourceFactory;
32+
33+
import static java.lang.System.Logger.Level.INFO;
34+
35+
@SuppressWarnings("unused")
36+
public class SecurityDocs
37+
{
38+
public void pathMapped() throws Exception
39+
{
40+
// tag::pathMapped[]
41+
class AppHandler extends Handler.Abstract
42+
{
43+
@Override
44+
public boolean handle(Request request, Response response, Callback callback)
45+
{
46+
// Retrieve the authenticated user for this request.
47+
Principal principal = Request.getAuthenticationState(request).getUserPrincipal();
48+
System.getLogger("app").log(INFO, "Current user is: {0}", principal);
49+
50+
callback.succeeded();
51+
return true;
52+
}
53+
}
54+
55+
Server server = new Server();
56+
57+
// The ContextHandler for the application.
58+
ContextHandler contextHandler = new ContextHandler("/app");
59+
60+
// HashLoginService maps users, passwords and roles
61+
// from the realm.properties file in the class-path.
62+
HashLoginService loginService = new HashLoginService();
63+
loginService.setConfig(ResourceFactory.of(contextHandler).newClassLoaderResource("realm.properties"));
64+
65+
// Use Basic authentication, which requires a secure transport.
66+
BasicAuthenticator authenticator = new BasicAuthenticator();
67+
authenticator.setLoginService(loginService);
68+
69+
// The SecurityHandler.PathMapped maps URI paths to constraints.
70+
SecurityHandler.PathMapped securityHandler = new SecurityHandler.PathMapped();
71+
securityHandler.setAuthenticator(authenticator);
72+
securityHandler.setLoginService(loginService);
73+
74+
// Configure constraints.
75+
// Require that all requests use a secure transport.
76+
securityHandler.put("/*", Constraint.SECURE_TRANSPORT);
77+
// URI paths that start with /admin/ can only be accessed by users with the "admin" role.
78+
securityHandler.put("/admin/*", Constraint.from("admin"));
79+
80+
// Link the Handlers.
81+
server.setHandler(contextHandler);
82+
contextHandler.setHandler(securityHandler);
83+
securityHandler.setHandler(new AppHandler());
84+
85+
server.start();
86+
// end::pathMapped[]
87+
}
88+
89+
public void pathMethodMapped() throws Exception
90+
{
91+
// tag::pathMethodMapped[]
92+
class AppHandler extends Handler.Abstract
93+
{
94+
@Override
95+
public boolean handle(Request request, Response response, Callback callback)
96+
{
97+
// Retrieve the authenticated user for this request.
98+
Principal principal = Request.getAuthenticationState(request).getUserPrincipal();
99+
System.getLogger("app").log(INFO, "Current user is: {0}", principal);
100+
101+
callback.succeeded();
102+
return true;
103+
}
104+
}
105+
106+
Server server = new Server();
107+
108+
// The ContextHandler for the application.
109+
ContextHandler contextHandler = new ContextHandler("/app");
110+
111+
// HashLoginService maps users, passwords and roles
112+
// from the realm.properties file in the class-path.
113+
HashLoginService loginService = new HashLoginService();
114+
loginService.setConfig(ResourceFactory.of(contextHandler).newClassLoaderResource("realm.properties"));
115+
116+
// Use Basic authentication, which requires a secure transport.
117+
BasicAuthenticator authenticator = new BasicAuthenticator();
118+
authenticator.setLoginService(loginService);
119+
120+
// The SecurityHandler.PathMapped maps URI paths to constraints.
121+
SecurityHandler.PathMethodMapped securityHandler = new SecurityHandler.PathMethodMapped();
122+
securityHandler.setAuthenticator(authenticator);
123+
securityHandler.setLoginService(loginService);
124+
125+
// Configure constraints.
126+
// Unless otherwise specified, access to resources is forbidden and requires secure transport.
127+
securityHandler.put("/*", "*", Constraint.combine(Constraint.FORBIDDEN, Constraint.SECURE_TRANSPORT));
128+
// GET /data/* is allowed only to users with the "read" role.
129+
securityHandler.put("/data/*", "GET", Constraint.from("read"));
130+
// PUT /data/* is allowed only to users with the "write" role.
131+
securityHandler.put("/data/*", "PUT", Constraint.from("write"));
132+
133+
// Link the Handlers.
134+
server.setHandler(contextHandler);
135+
contextHandler.setHandler(securityHandler);
136+
securityHandler.setHandler(new AppHandler());
137+
138+
server.start();
139+
// end::pathMethodMapped[]
140+
}
141+
142+
public void jakartaPathMapped() throws Exception
143+
{
144+
// tag::jakartaPathMapped[]
145+
Server server = new Server();
146+
147+
WebAppContext webApp = new WebAppContext();
148+
webApp.setContextPath("/app");
149+
webApp.setWar("/path/to/app.war");
150+
151+
// HashLoginService maps users, passwords and roles
152+
// from the realm.properties file in the server class-path.
153+
HashLoginService loginService = new HashLoginService();
154+
loginService.setConfig(ResourceFactory.of(webApp).newClassLoaderResource("realm.properties"));
155+
156+
// Use Basic authentication, which requires a secure transport.
157+
BasicAuthenticator authenticator = new BasicAuthenticator();
158+
authenticator.setLoginService(loginService);
159+
160+
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
161+
securityHandler.setAuthenticator(authenticator);
162+
securityHandler.setLoginService(loginService);
163+
164+
// Configure constraints.
165+
ConstraintMapping constraintMapping = new ConstraintMapping();
166+
constraintMapping.setPathSpec("/*");
167+
constraintMapping.setConstraint(Constraint.SECURE_TRANSPORT);
168+
securityHandler.addConstraintMapping(constraintMapping);
169+
constraintMapping = new ConstraintMapping();
170+
constraintMapping.setPathSpec("/admin/*");
171+
constraintMapping.setConstraint(Constraint.from("admin"));
172+
securityHandler.addConstraintMapping(constraintMapping);
173+
174+
// Link the Handlers.
175+
server.setHandler(webApp);
176+
// Note the specific call to setSecurityHandler().
177+
webApp.setSecurityHandler(securityHandler);
178+
179+
server.start();
180+
// end::jakartaPathMapped[]
181+
}
182+
183+
public void jakartaPathMethodMapped() throws Exception
184+
{
185+
// tag::jakartaPathMethodMapped[]
186+
Server server = new Server();
187+
188+
WebAppContext webApp = new WebAppContext();
189+
webApp.setContextPath("/app");
190+
webApp.setWar("/path/to/app.war");
191+
192+
// HashLoginService maps users, passwords and roles
193+
// from the realm.properties file in the server class-path.
194+
HashLoginService loginService = new HashLoginService();
195+
loginService.setConfig(ResourceFactory.of(webApp).newClassLoaderResource("realm.properties"));
196+
197+
// Use Basic authentication, which requires a secure transport.
198+
BasicAuthenticator authenticator = new BasicAuthenticator();
199+
authenticator.setLoginService(loginService);
200+
201+
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
202+
securityHandler.setAuthenticator(authenticator);
203+
securityHandler.setLoginService(loginService);
204+
205+
// Configure constraints.
206+
// Forbid access for uncovered HTTP methods.
207+
securityHandler.setDenyUncoveredHttpMethods(true);
208+
// No HTTP method specified, therefore applies to all methods.
209+
ConstraintMapping constraintMapping = new ConstraintMapping();
210+
constraintMapping.setPathSpec("/*");
211+
constraintMapping.setConstraint(Constraint.combine(Constraint.FORBIDDEN, Constraint.SECURE_TRANSPORT));
212+
securityHandler.addConstraintMapping(constraintMapping);
213+
// GET /data/* is allowed only to users with the "read" role.
214+
constraintMapping = new ConstraintMapping();
215+
constraintMapping.setPathSpec("/data/*");
216+
constraintMapping.setMethod("GET");
217+
constraintMapping.setConstraint(Constraint.combine(Constraint.SECURE_TRANSPORT, Constraint.from("read")));
218+
// PUT /data/* is allowed only to users with the "write" role.
219+
constraintMapping = new ConstraintMapping();
220+
constraintMapping.setPathSpec("/data/*");
221+
constraintMapping.setMethod("PUT");
222+
constraintMapping.setConstraint(Constraint.combine(Constraint.SECURE_TRANSPORT, Constraint.from("write")));
223+
224+
// Link the Handlers.
225+
server.setHandler(webApp);
226+
// Note the specific call to setSecurityHandler().
227+
webApp.setSecurityHandler(securityHandler);
228+
229+
server.start();
230+
// end::jakartaPathMethodMapped[]
231+
}
232+
}

0 commit comments

Comments
 (0)