From 13e00543c2cb79ad3c864fcf5177faa4ce4b2fd1 Mon Sep 17 00:00:00 2001 From: Rsl1122 <24460436+Rsl1122@users.noreply.github.com> Date: Mon, 16 Dec 2019 12:36:14 +0200 Subject: [PATCH] Implemented Access-Control-Allow-Origin - Added Config setting Webserver.Security.CORS.Allow_origin - Webserver returns the header for all requests - Added an HTTP 204 response for OPTIONS-method to speed up CORS requests. Affects issues: - Close #1251 --- .../delivery/webserver/RequestHandler.java | 5 +++- .../delivery/webserver/ResponseResolver.java | 5 ++++ .../webserver/response/OptionsResponse.java | 30 +++++++++++++++++++ .../config/paths/WebserverSettings.java | 1 + .../resources/assets/plan/bungeeconfig.yml | 4 +++ .../src/main/resources/assets/plan/config.yml | 4 +++ 6 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/response/OptionsResponse.java diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java index 8fd94640e..def3f084f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/RequestHandler.java @@ -24,6 +24,7 @@ import com.djrapitops.plan.delivery.webserver.response.ResponseFactory; import com.djrapitops.plan.delivery.webserver.response.errors.ForbiddenResponse; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.PluginSettings; +import com.djrapitops.plan.settings.config.paths.WebserverSettings; import com.djrapitops.plan.settings.locale.Locale; import com.djrapitops.plan.settings.theme.Theme; import com.djrapitops.plan.storage.database.DBSystem; @@ -96,7 +97,7 @@ public class RequestHandler implements HttpHandler { try { Response response = shouldPreventRequest(request.getRemoteAddress()) // Forbidden response (Optional) - .orElse(responseResolver.getResponse(request)); // Or the actual requested response + .orElseGet(() -> responseResolver.getResponse(request)); // Or the actual requested response // Increase attempt count and block if too high Optional forbid = handlePasswordBruteForceAttempts(request, response); @@ -109,6 +110,8 @@ public class RequestHandler implements HttpHandler { responseHeaders.set("WWW-Authenticate", response.getHeader("WWW-Authenticate").orElse("Basic realm=\"Plan WebUser (/plan register)\"")); } + responseHeaders.set("Access-Control-Allow-Origin", config.getString(WebserverSettings.CORS_ALLOW_ORIGIN)); + responseHeaders.set("Access-Control-Allow-Methods", "GET, OPTIONS"); response.setResponseHeaders(responseHeaders); response.send(exchange, locale, theme); } catch (Exception e) { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/ResponseResolver.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/ResponseResolver.java index acefdd7d3..94dfa6747 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/ResponseResolver.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/ResponseResolver.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.delivery.webserver; import com.djrapitops.plan.delivery.webserver.auth.Authentication; import com.djrapitops.plan.delivery.webserver.pages.*; import com.djrapitops.plan.delivery.webserver.pages.json.RootJSONResolver; +import com.djrapitops.plan.delivery.webserver.response.OptionsResponse; import com.djrapitops.plan.delivery.webserver.response.Response; import com.djrapitops.plan.delivery.webserver.response.ResponseFactory; import com.djrapitops.plan.exceptions.WebUserAuthException; @@ -116,6 +117,10 @@ public class ResponseResolver extends CompositePageResolver { RequestTarget target = request.getTarget(); String resource = target.getResourceString(); + if ("OPTIONS".equalsIgnoreCase(request.getRequestMethod())) { + return new OptionsResponse(); + } + if (target.endsWith(".css")) { return responseFactory.cssResponse(resource); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/response/OptionsResponse.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/response/OptionsResponse.java new file mode 100644 index 000000000..f108fc6c2 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/response/OptionsResponse.java @@ -0,0 +1,30 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.webserver.response; + +/** + * Response for an OPTIONS request. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS + * + * @author Rsl1122 + */ +public class OptionsResponse extends Response { + + public OptionsResponse() { + setHeader("HTTP/1.1 204 No Content"); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/config/paths/WebserverSettings.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/config/paths/WebserverSettings.java index 390e2b5fb..4a6761900 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/config/paths/WebserverSettings.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/config/paths/WebserverSettings.java @@ -32,6 +32,7 @@ public class WebserverSettings { public static final Setting SHOW_ALTERNATIVE_IP = new BooleanSetting("Webserver.Alternative_IP"); public static final Setting ALTERNATIVE_IP = new StringSetting("Webserver.Alternative_IP.Address"); public static final Setting INTERNAL_IP = new StringSetting("Webserver.Internal_IP"); + public static final Setting CORS_ALLOW_ORIGIN = new StringSetting("Webserver.Security.CORS.Allow_origin"); public static final Setting CERTIFICATE_PATH = new StringSetting("Webserver.Security.SSL_certificate.KeyStore_path"); public static final Setting CERTIFICATE_KEYPASS = new StringSetting("Webserver.Security.SSL_certificate.Key_pass"); public static final Setting CERTIFICATE_STOREPASS = new StringSetting("Webserver.Security.SSL_certificate.Store_pass"); diff --git a/Plan/common/src/main/resources/assets/plan/bungeeconfig.yml b/Plan/common/src/main/resources/assets/plan/bungeeconfig.yml index 335bc8174..1458e7b76 100644 --- a/Plan/common/src/main/resources/assets/plan/bungeeconfig.yml +++ b/Plan/common/src/main/resources/assets/plan/bungeeconfig.yml @@ -50,6 +50,10 @@ Webserver: Key_pass: default Store_pass: default Alias: alias + # Cross-Origin Resource Sharing (Requests from non-Plan web pages) + # https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + CORS: + Allow_origin: "*" Disable_Webserver: false External_Webserver_address: "https://www.example.address" # ----------------------------------------------------- diff --git a/Plan/common/src/main/resources/assets/plan/config.yml b/Plan/common/src/main/resources/assets/plan/config.yml index a7d753120..8c4d30c01 100644 --- a/Plan/common/src/main/resources/assets/plan/config.yml +++ b/Plan/common/src/main/resources/assets/plan/config.yml @@ -52,6 +52,10 @@ Webserver: Key_pass: default Store_pass: default Alias: alias + # Cross-Origin Resource Sharing (Requests from non-Plan web pages) + # https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + CORS: + Allow_origin: "*" Disable_Webserver: false External_Webserver_address: https://www.example.address # -----------------------------------------------------