add security context related j2html resources

This commit is contained in:
Jörg Prante 2024-04-15 17:23:37 +02:00
parent 6e83937cc1
commit c56634b281
21 changed files with 336 additions and 133 deletions

View file

@ -1,3 +1,3 @@
group = org.xbib
name = net-http
version = 4.4.3
version = 4.4.4

View file

@ -13,7 +13,7 @@ module org.xbib.net.http.client.netty.secure.test {
requires org.xbib.net.http;
requires org.xbib.net.http.client;
requires org.xbib.net.http.client.netty;
requires org.xbib.net.http.client.netty.secure;
requires transitive org.xbib.net.http.client.netty.secure;
requires io.netty.handler.proxy;
exports org.xbib.net.http.client.netty.secure.test;
opens org.xbib.net.http.client.netty.secure.test;

View file

@ -17,10 +17,12 @@ public class Https2Test {
private static final Logger logger = Logger.getLogger(Https2Test.class.getName());
@Disabled
public Https2Test() {
}
@Disabled("the xbib server does not offer HTTP/2 so this does not work!")
@Test
void testXbib() throws Exception {
// the xbib server does not offer HTTP/2 so this does not work!
NettyHttpClientConfig config = new NettyHttpsClientConfig()
.setDebug(true);
try (NettyHttpClient client = NettyHttpClient.builder()

View file

@ -22,6 +22,9 @@ public class JdkClientTest {
System.setProperty("javax.net.debug", "true");
}
public JdkClientTest() {
}
@Test
public void testDNB() throws Exception {
HttpClient httpClient = HttpClient.newBuilder()

View file

@ -1,6 +1,5 @@
package org.xbib.net.http.client.netty.secure.test;
import org.xbib.net.http.client.BackOff;
/**
@ -22,6 +21,9 @@ public class MockBackOff implements BackOff {
/** Number of tries so far. */
private int numTries;
public MockBackOff() {
}
@Override
public void reset() {
numTries = 0;

View file

@ -10,6 +10,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParameterTest {
public ParameterTest() {
}
@Test
public void testGetParametersWithSharedUrl() {
URL url = URL.from("http://example.com");

View file

@ -1,8 +1,7 @@
package org.xbib.net.http.server.application.web.j2html;
package org.xbib.net.http.j2html;
import org.xbib.net.Attributes;
import org.xbib.net.Resource;
import org.xbib.net.http.j2html.J2HtmlResourceHandler;
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
import org.xbib.net.http.server.route.HttpRouterContext;
import org.xbib.net.util.ExceptionFormatter;

View file

@ -0,0 +1,34 @@
package org.xbib.net.http.j2html;
import org.xbib.net.Resource;
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
import org.xbib.net.http.server.route.HttpRouterContext;
import java.io.IOException;
import java.nio.file.Path;
public class J2HtmlAuthResourceHandler extends HtmlTemplateResourceHandler {
public J2HtmlAuthResourceHandler() {
this(null, "java", "index.java");
}
public J2HtmlAuthResourceHandler(Path root, String suffix, String indexFileName) {
super(root, suffix, indexFileName);
}
@Override
protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException {
return httpRouterContext.isAuthenticated() ?
createAuthenticatedResource(httpRouterContext) :
createUnauthenticatedResource(httpRouterContext);
}
protected Resource createAuthenticatedResource(HttpRouterContext httpRouterContext) throws IOException {
return new J2HtmlResource(this, httpRouterContext);
}
protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) throws IOException {
return new J2HtmlResource(this, httpRouterContext);
}
}

View file

@ -0,0 +1,57 @@
package org.xbib.net.http.j2html;
import org.xbib.net.buffer.DataBuffer;
import org.xbib.net.http.HttpResponseStatus;
import org.xbib.net.http.server.HttpRequest;
import org.xbib.net.http.server.resource.HtmlTemplateResource;
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
import org.xbib.net.http.server.route.HttpRouterContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import static org.xbib.j2html.TagCreator.body;
import static org.xbib.j2html.TagCreator.h1;
import static org.xbib.net.http.HttpHeaderNames.CONTENT_TYPE;
public class J2HtmlResource extends HtmlTemplateResource {
protected HttpRequest request;
public J2HtmlResource(HtmlTemplateResourceHandler templateResourceHandler,
HttpRouterContext httpRouterContext) throws IOException {
super(templateResourceHandler, httpRouterContext);
}
@Override
public void render(HttpRouterContext context) throws IOException {
this.request = context.getRequest();
Objects.requireNonNull(responseBuilder);
DataBuffer dataBuffer = context.getDataBufferFactory().allocateBuffer();
dataBuffer.write(renderBody(context), StandardCharsets.UTF_8);
HttpResponseStatus httpResponseStatus = responseBuilder.getResponseStatus();
if (httpResponseStatus == null) {
httpResponseStatus = HttpResponseStatus.OK;
}
context.status(httpResponseStatus)
.header("cache-control", "no-cache") // override default must-revalidate behavior
.header("content-length", Integer.toString(dataBuffer.writePosition()))
.header(CONTENT_TYPE, "text/html; charset=" + StandardCharsets.UTF_8.displayName())
.body(dataBuffer);
}
/**
* Rendering a body.
* By subclassing this handler, this method should be overridden by custom j2html code.
* The body here is just a greeting as an example.
*
* @param context the router context
* @return the body string fo the HTTP response
*/
protected String renderBody(HttpRouterContext context) {
return body(
h1("Hello World")
).render();
}
}

View file

@ -1,21 +1,14 @@
package org.xbib.net.http.j2html;
import org.xbib.net.Resource;
import org.xbib.net.buffer.DataBuffer;
import org.xbib.net.http.HttpResponseStatus;
import org.xbib.net.http.server.HttpRequest;
import org.xbib.net.http.server.resource.HtmlTemplateResource;
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
import org.xbib.net.http.server.route.HttpRouterContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Objects;
import static org.xbib.j2html.TagCreator.body;
import static org.xbib.j2html.TagCreator.h1;
import static org.xbib.net.http.HttpHeaderNames.CONTENT_TYPE;
public class J2HtmlResourceHandler extends HtmlTemplateResourceHandler {
@ -31,43 +24,4 @@ public class J2HtmlResourceHandler extends HtmlTemplateResourceHandler {
protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException {
return new J2HtmlResource(this, httpRouterContext);
}
protected static class J2HtmlResource extends HtmlTemplateResource {
protected HttpRequest request;
protected J2HtmlResource(HtmlTemplateResourceHandler templateResourceHandler,
HttpRouterContext httpRouterContext) throws IOException {
super(templateResourceHandler, httpRouterContext);
}
@Override
public void render(HttpRouterContext context) throws IOException {
this.request = context.getRequest();
Objects.requireNonNull(responseBuilder);
DataBuffer dataBuffer = context.getDataBufferFactory().allocateBuffer();
dataBuffer.write(renderBody(context), StandardCharsets.UTF_8);
HttpResponseStatus httpResponseStatus = responseBuilder.getResponseStatus();
if (httpResponseStatus == null) {
httpResponseStatus = HttpResponseStatus.OK;
}
context.status(httpResponseStatus)
.header("cache-control", "no-cache") // override default must-revalidate behavior
.header("content-length", Integer.toString(dataBuffer.writePosition()))
.header(CONTENT_TYPE, "text/html; charset=" + StandardCharsets.UTF_8.displayName())
.body(dataBuffer);
}
/**
* By subclassing this handler, this method should be overriden by custom j2html code.
* The body here is just a greeting as an example.
* @param context the router context
* @return the body string fo the HTTP response
*/
protected String renderBody(HttpRouterContext context) {
return body(
h1("Hello World")
).render();
}
}
}

View file

@ -24,7 +24,6 @@ import org.xbib.net.http.server.executor.Executor;
import org.xbib.net.http.server.route.HttpRouter;
import org.xbib.net.http.server.service.HttpService;
import org.xbib.net.http.server.auth.BasicAuthenticationHandler;
import org.xbib.net.http.server.auth.FormAuthenticationHandler;
import org.xbib.net.http.server.ldap.LdapContextFactory;
import org.xbib.net.http.server.ldap.LdapGroupMapping;
import org.xbib.net.http.server.ldap.LdapRealm;
@ -37,6 +36,7 @@ import org.xbib.net.http.server.netty.secure.HttpsAddress;
import org.xbib.net.http.server.netty.secure.HttpsRequest;
import org.xbib.net.http.server.netty.secure.NettyHttpsServerConfig;
import org.xbib.net.http.server.resource.ClassLoaderResourceHandler;
import org.xbib.net.http.template.groovy.GroovyFormAuthenticationHandler;
import org.xbib.net.http.template.groovy.GroovyInternalServerErrorHandler;
import org.xbib.net.http.template.groovy.GroovyHttpStatusHandler;
import org.xbib.net.http.template.groovy.GroovyTemplateResourceHandler;
@ -125,9 +125,9 @@ public final class Bootstrap {
BasicAuthenticationHandler basicAuthenticationHandler =
new BasicAuthenticationHandler(ldapRealm);
FormAuthenticationHandler formAuthenticationHandler =
new FormAuthenticationHandler("j_username", "j_password", "j_remember",
"demo/auth/form/index.gtpl", ldapRealm);
GroovyFormAuthenticationHandler formAuthenticationHandler =
new GroovyFormAuthenticationHandler("j_username", "j_password",
ldapRealm, "demo/auth/form/index.gtpl");
HttpSecurityDomain securityDomain = BaseHttpSecurityDomain.builder()
.setSecurityRealm(ldapRealm)

View file

@ -5,11 +5,14 @@ import org.xbib.config.ConfigLogger;
import org.xbib.config.ConfigParams;
import org.xbib.config.SystemConfigLogger;
import org.xbib.net.NetworkClass;
import org.xbib.net.Resource;
import org.xbib.net.http.HttpHeaderNames;
import org.xbib.net.http.HttpHeaderValues;
import org.xbib.net.http.HttpResponseStatus;
import org.xbib.net.http.HttpVersion;
import org.xbib.net.http.j2html.J2HtmlResourceHandler;
import org.xbib.net.http.j2html.InternalServerErrorHandler;
import org.xbib.net.http.j2html.J2HtmlAuthResourceHandler;
import org.xbib.net.http.j2html.J2HtmlResource;
import org.xbib.net.http.j2html.J2HtmlService;
import org.xbib.net.http.server.application.web.WebApplication;
import org.xbib.net.http.server.auth.BasicAuthenticationHandler;
@ -29,12 +32,14 @@ import org.xbib.net.http.server.netty.secure.HttpsAddress;
import org.xbib.net.http.server.netty.secure.HttpsRequest;
import org.xbib.net.http.server.netty.secure.NettyHttpsServerConfig;
import org.xbib.net.http.server.resource.ClassLoaderResourceHandler;
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
import org.xbib.net.http.server.route.BaseHttpRouter;
import org.xbib.net.http.server.route.HttpRouter;
import org.xbib.net.http.server.route.HttpRouterContext;
import org.xbib.net.http.server.service.BaseHttpService;
import org.xbib.net.http.server.service.HttpService;
import org.xbib.settings.Settings;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@ -42,6 +47,9 @@ import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import static org.xbib.j2html.TagCreator.body;
import static org.xbib.j2html.TagCreator.h1;
public final class Bootstrap {
private static final ConfigLogger bootLogger;
@ -125,32 +133,13 @@ public final class Bootstrap {
new BasicAuthenticationHandler(ldapRealm);
FormAuthenticationHandler formAuthenticationHandler =
new FormAuthenticationHandler("j_username", "j_password", "j_remember",
"demo/auth/form/index.gtpl", ldapRealm);
new FormAuthenticationHandler("_username", "_password", ldapRealm);
HttpSecurityDomain securityDomain = BaseHttpSecurityDomain.builder()
.setSecurityRealm(ldapRealm)
.setHandlers(formAuthenticationHandler)
.build();
HttpService httpService = BaseHttpService.builder()
.setPath("/secure")
.setHandler(ctx -> {
ctx.status(HttpResponseStatus.OK)
.header(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN)
.charset(StandardCharsets.UTF_8)
.body("secure domain: " +
" SNI host = " + ctx.getRequest().as(HttpsRequest.class).getSNIHost() +
" SSL session = " + ctx.getRequest().as(HttpsRequest.class).getSSLSession() +
" base URL = " + ctx.getRequest().getBaseURL() +
" parameter = " + ctx.getRequest().getParameter().toString() +
" attributes = " + ctx.getAttributes() +
" local address = " + ctx.getRequest().getLocalAddress() +
" remote address = " + ctx.getRequest().getRemoteAddress());
ctx.done();
})
.build();
HttpRouter httpRouter = BaseHttpRouter.builder()
.setHandler(500, new InternalServerErrorHandler())
.addDomain(BaseHttpDomain.builder()
@ -168,10 +157,27 @@ public final class Bootstrap {
.setPath("/webjars/**")
.setHandler(new ClassLoaderResourceHandler(Bootstrap.class.getClassLoader(), "META-INF/resources/"))
.build())
.addService(httpService)
.addService(BaseHttpService.builder()
.setPath("/insecure")
.setHandler(ctx -> {
ctx.status(HttpResponseStatus.OK)
.header(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN)
.charset(StandardCharsets.UTF_8)
.body("secure domain: " +
" SNI host = " + ctx.getRequest().as(HttpsRequest.class).getSNIHost() +
" SSL session = " + ctx.getRequest().as(HttpsRequest.class).getSSLSession() +
" base URL = " + ctx.getRequest().getBaseURL() +
" parameter = " + ctx.getRequest().getParameter().toString() +
" attributes = " + ctx.getAttributes() +
" local address = " + ctx.getRequest().getLocalAddress() +
" remote address = " + ctx.getRequest().getRemoteAddress());
ctx.done();
})
.build())
.addService(J2HtmlService.builder()
.setPath("glob:**")
.setHandler(new J2HtmlResourceHandler())
.setSecurityDomain(securityDomain)
.setHandler(new MyResourceHandler())
.build())
.build())
.build();
@ -197,6 +203,47 @@ public final class Bootstrap {
return 0;
}
static class MyResourceHandler extends J2HtmlAuthResourceHandler {
@Override
protected Resource createAuthenticatedResource(HttpRouterContext httpRouterContext) throws IOException {
return new DemoResource(this, httpRouterContext);
}
@Override
protected Resource createUnauthenticatedResource(HttpRouterContext httpRouterContext) throws IOException {
return new UnauthenticatedDemoResource(this, httpRouterContext);
}
}
static class DemoResource extends J2HtmlResource {
public DemoResource(HtmlTemplateResourceHandler templateResourceHandler,
HttpRouterContext httpRouterContext) throws IOException {
super(templateResourceHandler, httpRouterContext);
}
protected String renderBody(HttpRouterContext context) {
return body(
h1("This is a demo")
).render();
}
}
static class UnauthenticatedDemoResource extends J2HtmlResource {
public UnauthenticatedDemoResource(HtmlTemplateResourceHandler templateResourceHandler,
HttpRouterContext httpRouterContext) throws IOException {
super(templateResourceHandler, httpRouterContext);
}
protected String renderBody(HttpRouterContext context) {
return body(
h1("This is a demo, unauthenticated")
).render();
}
}
private static final String hexFavIcon =
"000001000100101000000100200068040000160000002800000010000000" +
"200000000100200000000000000000000000000000000000000000000000" +

View file

@ -26,6 +26,9 @@ public class SimpleHttpsServerTest {
private static final Logger logger = Logger.getLogger(SimpleHttpsServerTest.class.getName());
public SimpleHttpsServerTest() {
}
@Test
public void simpleSecureHttpsServerTest() throws Exception {
HttpsAddress httpsAddress = HttpsAddress.builder()

View file

@ -1,5 +1,6 @@
package org.xbib.net.http.server.application;
@FunctionalInterface
public interface Resolver<R> {
R resolve(String string);

View file

@ -50,6 +50,6 @@ public class BasicAuthenticationHandler extends LoginAuthenticationHandler imple
}
logger.log(Level.INFO, "unauthenticated");
context.status(HttpResponseStatus.UNAUTHORIZED)
.header("WWW-Authenticate", "Basic realm=\"" + securityRealm.getName() + "\"");
.header("WWW-Authenticate", "Basic realm=\"" + getSecurityRealm().getName() + "\"");
}
}

View file

@ -15,73 +15,60 @@ public class FormAuthenticationHandler extends LoginAuthenticationHandler implem
private static final Logger logger = Logger.getLogger(FormAuthenticationHandler.class.getName());
String usernameParameter;
String passwordParameter;
String rememberParameter;
String loginPage;
public FormAuthenticationHandler(String usernameParameter,
String passwordParameter,
String rememberParameter,
String loginPage,
SecurityRealm securityRealm) {
super(usernameParameter, passwordParameter, securityRealm);
this.usernameParameter = usernameParameter;
this.passwordParameter = passwordParameter;
this.rememberParameter = rememberParameter;
this.loginPage = loginPage;
}
@Override
public void handle(HttpRouterContext context) throws IOException {
if (loginPage == null) {
logger.log(Level.WARNING, "no loginPage configured");
return;
}
UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile");
if (userProfile != null && userProfile.getUserId() != null) {
logger.log(Level.FINE, "user id already set: " + userProfile.getUserId());
return;
}
// always add an "anonymous" user profile
if (context.isAuthenticated()) {
logger.log(Level.FINE, "context already authenticated");
return;
}
// always add an "anonymous" user profile with a null user ID
userProfile = new BaseUserProfile();
context.getAttributes().put("userprofile", userProfile);
boolean isAuthenticated = false;
try {
Parameter parameter = context.getRequest().getParameter();
if (!parameter.containsKey(usernameParameter, Parameter.Domain.FORM)) {
if (!parameter.containsKey(getUserParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "usernameParameter not set, unable to authenticate");
prepareFormAuthentication(context);
return;
}
if (!parameter.containsKey(passwordParameter, Parameter.Domain.FORM)) {
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
if (!parameter.containsKey(getPasswordParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "passwordParameter not set, unable to authenticate");
prepareFormAuthentication(context);
return;
}
try {
String username = parameter.getAsString(usernameParameter, Parameter.Domain.FORM);
String password = parameter.getAsString(passwordParameter, Parameter.Domain.FORM);
logger.log(Level.FINE, "username and password found, ready for authentication");
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
authenticate(userProfile, username, password, context.getRequest());
logger.log(Level.FINE, "successful authentication");
return;
isAuthenticated = true;
} catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) {
logger.log(Level.SEVERE, "authentication error");
}
} finally {
context.setAuthenticated(isAuthenticated);
if (!isAuthenticated) {
prepareFormAuthentication(context);
}
}
}
private void prepareFormAuthentication(HttpRouterContext context) {
// this will redirect internally to login page, and back to the original path.
// We need a full path resolve against the server URL.
logger.log(Level.FINE, "templatePath = " + loginPage);
context.getAttributes().put("templatePath", loginPage);
URL loc = context.getContextURL().resolve(context.getRequest().getRequestURI()).normalize();
logger.log(Level.FINE, "context URL = " + context.getContextURL() + " request URI = " + context.getRequest().getRequestURI() + " loc = " + loc);
context.getAttributes().put("originalPath", loc.toExternalForm());
protected void prepareFormAuthentication(HttpRouterContext context) {
URL origin = context.getContextURL().resolve(context.getRequest().getRequestURI()).normalize();
logger.log(Level.FINE, "context URL = " + context.getContextURL() +
" request URI = " + context.getRequest().getRequestURI() +
" origin = " + origin);
context.getAttributes().put("_origin", origin.toExternalForm());
}
}

View file

@ -7,6 +7,7 @@ import java.util.logging.Logger;
import org.xbib.net.Authenticator;
import org.xbib.net.GroupsProvider;
import org.xbib.net.Parameter;
import org.xbib.net.ParameterException;
import org.xbib.net.Request;
import org.xbib.net.SecurityRealm;
import org.xbib.net.UserDetails;
@ -23,7 +24,7 @@ public class LoginAuthenticationHandler implements HttpHandler {
private final String passwordParameterName;
protected final SecurityRealm securityRealm;
private final SecurityRealm securityRealm;
public LoginAuthenticationHandler(String userParameterName,
String passwordParameterName,
@ -33,21 +34,39 @@ public class LoginAuthenticationHandler implements HttpHandler {
this.securityRealm = securityRealm;
}
public String getUserParameterName() {
return userParameterName;
}
public String getPasswordParameterName() {
return passwordParameterName;
}
public SecurityRealm getSecurityRealm() {
return securityRealm;
}
@Override
public void handle(HttpRouterContext context) throws IOException {
UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile");
if (userProfile != null && userProfile.getUserId() != null) {
return;
}
Parameter parameter = context.getRequest().getParameter();
userProfile = new BaseUserProfile();
try {
authenticate(userProfile,
(String) context.getRequest().getParameter().get(userParameterName, Parameter.Domain.FORM),
(String) context.getRequest().getParameter().get(passwordParameterName, Parameter.Domain.FORM),
context.getRequest());
context.getAttributes().put("userprofile", userProfile);
boolean isAuthenticated = false;
try {
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
authenticate(userProfile, username, password, context.getRequest());
isAuthenticated = true;
} catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) {
logger.log(Level.SEVERE, "authentication error");
} finally {
context.setAuthenticated(isAuthenticated);
}
}

View file

@ -57,6 +57,8 @@ public class BaseHttpRouterContext implements HttpRouterContext {
private boolean next;
private boolean isAuthenticated;
public BaseHttpRouterContext(Application application,
HttpDomain domain,
HttpRequestBuilder httpRequestBuilder,
@ -280,6 +282,15 @@ public class BaseHttpRouterContext implements HttpRouterContext {
return httpResponseBuilder.getLength();
}
public void setAuthenticated(boolean isAuthenticated) {
this.isAuthenticated = isAuthenticated;
}
@Override
public boolean isAuthenticated() {
return isAuthenticated;
}
@Override
public void flush() throws IOException {
httpResponseBuilder.build().flush();

View file

@ -97,6 +97,10 @@ public interface HttpRouterContext {
long lengthInBytes();
void setAuthenticated(boolean isAuthenticated);
boolean isAuthenticated();
void flush() throws IOException;
void close() throws IOException;

View file

@ -0,0 +1,77 @@
package org.xbib.net.http.template.groovy;
import org.xbib.net.Parameter;
import org.xbib.net.ParameterException;
import org.xbib.net.SecurityRealm;
import org.xbib.net.URL;
import org.xbib.net.UserProfile;
import org.xbib.net.http.server.auth.BaseUserProfile;
import org.xbib.net.http.server.auth.FormAuthenticationHandler;
import org.xbib.net.http.server.route.HttpRouterContext;
import java.io.IOException;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
public class GroovyFormAuthenticationHandler extends FormAuthenticationHandler {
private static final Logger logger = Logger.getLogger(GroovyFormAuthenticationHandler.class.getName());
private final String loginTemplate;
public GroovyFormAuthenticationHandler(String usernameParameter,
String passwordParameter,
SecurityRealm securityRealm,
String loginTemplate) {
super(usernameParameter, passwordParameter, securityRealm);
this.loginTemplate = Objects.requireNonNull(loginTemplate, "no login template configured");
}
@Override
public void handle(HttpRouterContext context) throws IOException {
UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile");
if (userProfile != null && userProfile.getUserId() != null) {
logger.log(Level.FINE, "user id already set: " + userProfile.getUserId());
return;
}
// always add an "anonymous" user profile
userProfile = new BaseUserProfile();
context.getAttributes().put("userprofile", userProfile);
Parameter parameter = context.getRequest().getParameter();
if (!parameter.containsKey(getUserParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "usernameParameter not set, unable to authenticate");
prepareFormAuthentication(context);
return;
}
if (!parameter.containsKey(getPasswordParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "passwordParameter not set, unable to authenticate");
prepareFormAuthentication(context);
return;
}
try {
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
logger.log(Level.FINE, "username and password found, ready for authentication");
authenticate(userProfile, username, password, context.getRequest());
logger.log(Level.FINE, "successful authentication");
return;
} catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) {
logger.log(Level.SEVERE, "authentication error");
}
prepareFormAuthentication(context);
}
@Override
protected void prepareFormAuthentication(HttpRouterContext context) {
// this will redirect internally to login page, and back to the original path.
// We need a full path resolve against the server URL.
logger.log(Level.FINE, "set new templatePath, login template = " + loginTemplate);
context.getAttributes().put("templatePath", loginTemplate);
URL loc = context.getContextURL().resolve(context.getRequest().getRequestURI()).normalize();
logger.log(Level.FINE, "context URL = " + context.getContextURL() + " request URI = " + context.getRequest().getRequestURI() + " loc = " + loc);
context.getAttributes().put("originalPath", loc.toExternalForm());
}
}

View file

@ -50,7 +50,7 @@ public class GroovyTemplateServiceBuilder extends BaseHttpServiceBuilder {
}
@Override
public BaseHttpServiceBuilder setSecurityDomain(HttpSecurityDomain securityDomain) {
public GroovyTemplateServiceBuilder setSecurityDomain(HttpSecurityDomain securityDomain) {
super.setSecurityDomain(securityDomain);
return this;
}