You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2018/04/20 10:58:08 UTC
[1/2] lucene-solr:solr7896-login-page: WIP testing HTTP interceptors
Repository: lucene-solr
Updated Branches:
refs/heads/solr7896-login-page [created] f70371bab
WIP testing HTTP interceptors
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/0fc0ff23
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/0fc0ff23
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/0fc0ff23
Branch: refs/heads/solr7896-login-page
Commit: 0fc0ff23ae91509cc135dfa425df469559dd76a0
Parents: 1c8ab33
Author: Jan Høydahl <ja...@apache.org>
Authored: Thu Apr 19 11:23:43 2018 +0200
Committer: Jan Høydahl <ja...@apache.org>
Committed: Thu Apr 19 11:23:43 2018 +0200
----------------------------------------------------------------------
solr/bin/solr.in.sh | 8 ++++++++
solr/webapp/web/js/angular/app.js | 24 ++++++++++++++++++++++++
2 files changed, 32 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0fc0ff23/solr/bin/solr.in.sh
----------------------------------------------------------------------
diff --git a/solr/bin/solr.in.sh b/solr/bin/solr.in.sh
index 7cf6a84..04ac46c 100644
--- a/solr/bin/solr.in.sh
+++ b/solr/bin/solr.in.sh
@@ -171,3 +171,11 @@
#SOLR_RECOMMENDED_MAX_PROCESSES=
#SOLR_ULIMIT_CHECKS=
+
+# The following lines added by ./solr for enabling BasicAuth
+# SOLR_AUTH_TYPE="basic"
+# SOLR_AUTHENTICATION_OPTS="-Dsolr.httpclient.config=/Users/janhoy/git/lucene-solr/solr/server/solr/basicAuth.conf"
+
+# The following lines added by ./solr for enabling BasicAuth
+SOLR_AUTH_TYPE="basic"
+SOLR_AUTHENTICATION_OPTS="-Dsolr.httpclient.config=/Users/janhoy/git/lucene-solr/solr/server/solr/basicAuth.conf"
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0fc0ff23/solr/webapp/web/js/angular/app.js
----------------------------------------------------------------------
diff --git a/solr/webapp/web/js/angular/app.js b/solr/webapp/web/js/angular/app.js
index ad96ce0..ee420d3 100644
--- a/solr/webapp/web/js/angular/app.js
+++ b/solr/webapp/web/js/angular/app.js
@@ -369,8 +369,32 @@ solrAdminApp.config([
return {request: started, response: ended, responseError: failed};
})
+.factory('authInterceptor', function($q, $rootScope, $timeout, $injector) {
+ var started = function(config) {
+ config.headers['Authorization'] = "Basic c29scjpTb2xyUm9ja3M="; // solr / solrRocks
+ console.log("Added authorization header");
+ return config || $q.when(config);
+ };
+
+ var ended = function(response) {
+ if (response.headers['WWW-Authenticate'] != null) {
+ console.log("Got WWW-Authenticate header");
+ alert("WWW-Authenticate: " + response.headers['WWW-Authenticate']);
+ }
+ return response || $q.when(response);
+ };
+
+ var failed = function(rejection) {
+ console.log("Failed with rejection " + rejection);
+ $rootScope.$broadcast('loadingStatusInactive');
+ return $q.reject(rejection);
+ };
+
+ return {request: started, response: ended, responseError: failed};
+})
.config(function($httpProvider) {
$httpProvider.interceptors.push("httpInterceptor");
+ $httpProvider.interceptors.push("authInterceptor");
})
.directive('fileModel', function ($parse) {
return {
[2/2] lucene-solr:solr7896-login-page: Hard coded authentication with
solr:solrRocks
Posted by ja...@apache.org.
Hard coded authentication with solr:solrRocks
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f70371ba
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f70371ba
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f70371ba
Branch: refs/heads/solr7896-login-page
Commit: f70371bab49e3838955dbab9d2e8b85589817afe
Parents: 0fc0ff2
Author: Jan Høydahl <ja...@apache.org>
Authored: Fri Apr 20 12:36:35 2018 +0200
Committer: Jan Høydahl <ja...@apache.org>
Committed: Fri Apr 20 12:36:35 2018 +0200
----------------------------------------------------------------------
.../apache/solr/security/BasicAuthPlugin.java | 35 +++++++++++++----
.../apache/solr/servlet/SolrDispatchFilter.java | 41 +++++++++++++-------
solr/webapp/web/WEB-INF/web.xml | 2 +-
solr/webapp/web/js/angular/app.js | 17 +++++---
4 files changed, 66 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f70371ba/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java b/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
index eab89e3..3533b9e 100644
--- a/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java
@@ -34,12 +34,13 @@ import java.util.StringTokenizer;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
import org.apache.http.auth.BasicUserPrincipal;
import org.apache.http.message.BasicHeader;
import org.apache.solr.common.SolrException;
-import org.apache.solr.common.util.ValidatingJsonMap;
-import org.apache.solr.common.util.CommandOperation;
import org.apache.solr.common.SpecProvider;
+import org.apache.solr.common.util.CommandOperation;
+import org.apache.solr.common.util.ValidatingJsonMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,6 +48,7 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private AuthenticationProvider authenticationProvider;
private final static ThreadLocal<Header> authHeader = new ThreadLocal<>();
+ private static final String X_REQUESTED_WITH_HEADER = "X-Requested-With";
private boolean blockUnknown = false;
public boolean authenticate(String username, String pwd) {
@@ -94,9 +96,17 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
return provider;
}
- private void authenticationFailure(HttpServletResponse response, String message) throws IOException {
+ private void authenticationFailure(HttpServletResponse response, boolean isAjaxRequest, String message) throws IOException {
for (Map.Entry<String, String> entry : authenticationProvider.getPromptHeaders().entrySet()) {
- response.setHeader(entry.getKey(), entry.getValue());
+ String value = entry.getValue();
+ // Prevent browser from intercepting basic authentication header when reqeust from Admin UI
+ if (isAjaxRequest && HttpHeaders.WWW_AUTHENTICATE.equalsIgnoreCase(entry.getKey()) && value != null) {
+ if (value.startsWith("Basic ")) {
+ value = "x" + value;
+ log.debug("Prefixing {} header for Basic Auth with 'x' to prevent browser basic auth popup", HttpHeaders.WWW_AUTHENTICATE);
+ }
+ }
+ response.setHeader(entry.getKey(), value);
}
response.sendError(401, message);
}
@@ -108,6 +118,8 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
HttpServletResponse response = (HttpServletResponse) servletResponse;
String authHeader = request.getHeader("Authorization");
+ boolean isAjaxRequest = isAjaxRequest(request);
+
if (authHeader != null) {
BasicAuthPlugin.authHeader.set(new BasicHeader("Authorization", authHeader));
StringTokenizer st = new StringTokenizer(authHeader);
@@ -122,7 +134,7 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
String pwd = credentials.substring(p + 1).trim();
if (!authenticate(username, pwd)) {
log.debug("Bad auth credentials supplied in Authorization header");
- authenticationFailure(response, "Bad credentials");
+ authenticationFailure(response, isAjaxRequest, "Bad credentials");
} else {
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
@Override
@@ -135,7 +147,7 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
}
} else {
- authenticationFailure(response, "Invalid authentication token");
+ authenticationFailure(response, isAjaxRequest, "Invalid authentication token");
}
} catch (UnsupportedEncodingException e) {
throw new Error("Couldn't retrieve authentication", e);
@@ -144,7 +156,7 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
}
} else {
if (blockUnknown) {
- authenticationFailure(response, "require authentication");
+ authenticationFailure(response, isAjaxRequest, "require authentication");
} else {
request.setAttribute(AuthenticationPlugin.class.getName(), authenticationProvider.getPromptHeaders());
filterChain.doFilter(request, response);
@@ -183,5 +195,12 @@ public class BasicAuthPlugin extends AuthenticationPlugin implements ConfigEdita
public static final String BLOCK_UNKNOWN = "blockUnknown";
private static final Set<String> PROPS = ImmutableSet.of(BLOCK_UNKNOWN);
-
+ /**
+ * Check if the request is an AJAX request, i.e. from the Admin UI or other SPA front
+ * @param request the servlet request
+ * @return true if the request is AJAX request
+ */
+ private boolean isAjaxRequest(HttpServletRequest request) {
+ return "XMLHttpRequest".equalsIgnoreCase(request.getHeader(X_REQUESTED_WITH_HEADER));
+ }
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f70371ba/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index fc0c28f..5f8097c 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -358,18 +358,6 @@ public class SolrDispatchFilter extends BaseSolrFilter {
}
}
- AtomicReference<HttpServletRequest> wrappedRequest = new AtomicReference<>();
- if (!authenticateRequest(request, response, wrappedRequest)) { // the response and status code have already been sent
- return;
- }
- if (wrappedRequest.get() != null) {
- request = wrappedRequest.get();
- }
-
- if (cores.getAuthenticationPlugin() != null) {
- log.debug("User principal: {}", request.getUserPrincipal());
- }
-
// No need to even create the HttpSolrCall object if this path is excluded.
if (excludePatterns != null) {
String requestPath = request.getServletPath();
@@ -387,6 +375,18 @@ public class SolrDispatchFilter extends BaseSolrFilter {
}
}
+ AtomicReference<HttpServletRequest> wrappedRequest = new AtomicReference<>();
+ if (!authenticateRequest(request, response, wrappedRequest)) { // the response and status code have already been sent
+ return;
+ }
+ if (wrappedRequest.get() != null) {
+ request = wrappedRequest.get();
+ }
+
+ if (cores.getAuthenticationPlugin() != null) {
+ log.debug("User principal: {}", request.getUserPrincipal());
+ }
+
HttpSolrCall call = getHttpSolrCall(closeShield(request, retry), closeShield(response, retry), retry);
ExecutorUtil.setServerThreadFlag(Boolean.TRUE);
try {
@@ -453,11 +453,22 @@ public class SolrDispatchFilter extends BaseSolrFilter {
if (authenticationPlugin == null) {
return true;
} else {
- // /admin/info/key must be always open. see SOLR-9188
+ // /admin/info/key and /solr/ (Admin UI) must be always open. see SOLR-9188
// tests work only w/ getPathInfo
//otherwise it's just enough to have getServletPath()
- if (PKIAuthenticationPlugin.PATH.equals(request.getServletPath()) ||
- PKIAuthenticationPlugin.PATH.equals(request.getPathInfo())) return true;
+ String requestPath = request.getPathInfo();
+ if (requestPath == null)
+ requestPath = request.getServletPath();
+ if (PKIAuthenticationPlugin.PATH.equals(requestPath)) {
+ if (log.isDebugEnabled())
+ log.debug("Pass through PKI authentication endpoint");
+ return true;
+ }
+ if ("/solr/".equals(requestPath) || "/".equals(requestPath)) {
+ if (log.isDebugEnabled())
+ log.debug("Pass through Admin UI entry point");
+ return true;
+ }
String header = request.getHeader(PKIAuthenticationPlugin.HEADER);
if (header != null && cores.getPkiAuthenticationPlugin() != null)
authenticationPlugin = cores.getPkiAuthenticationPlugin();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f70371ba/solr/webapp/web/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/solr/webapp/web/WEB-INF/web.xml b/solr/webapp/web/WEB-INF/web.xml
index 8d86269..22082c8 100644
--- a/solr/webapp/web/WEB-INF/web.xml
+++ b/solr/webapp/web/WEB-INF/web.xml
@@ -56,7 +56,7 @@
-->
<init-param>
<param-name>excludePatterns</param-name>
- <param-value>/partials/.+,/libs/.+,/css/.+,/js/.+,/img/.+,/tpl/.+</param-value>
+ <param-value>/partials/.+,/libs/.+,/css/.+,/js/.+,/img/.+</param-value>
</init-param>
</filter>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f70371ba/solr/webapp/web/js/angular/app.js
----------------------------------------------------------------------
diff --git a/solr/webapp/web/js/angular/app.js b/solr/webapp/web/js/angular/app.js
index ee420d3..3a2009a 100644
--- a/solr/webapp/web/js/angular/app.js
+++ b/solr/webapp/web/js/angular/app.js
@@ -371,21 +371,25 @@ solrAdminApp.config([
})
.factory('authInterceptor', function($q, $rootScope, $timeout, $injector) {
var started = function(config) {
- config.headers['Authorization'] = "Basic c29scjpTb2xyUm9ja3M="; // solr / solrRocks
- console.log("Added authorization header");
+ var ah = "Basic c29scjpzb2xyUm9ja3M="; // solr / solrRocks
+ config.headers['Authorization'] = ah;
+ console.log("Added authorization header " + ah);
return config || $q.when(config);
};
var ended = function(response) {
+ console.log("Response headers: " + JSON.stringify(response.headers, undefined, 2));
if (response.headers['WWW-Authenticate'] != null) {
- console.log("Got WWW-Authenticate header");
- alert("WWW-Authenticate: " + response.headers['WWW-Authenticate']);
+ console.log("Got WWW-Authenticate header: " + response.headers['WWW-Authenticate']);
}
return response || $q.when(response);
};
var failed = function(rejection) {
- console.log("Failed with rejection " + rejection);
+ console.log("Failed with rejection " + JSON.stringify(rejection, undefined, 2));
+ if (rejection.status === 401) {
+ console.log("Status code is 401");
+ }
$rootScope.$broadcast('loadingStatusInactive');
return $q.reject(rejection);
};
@@ -395,6 +399,9 @@ solrAdminApp.config([
.config(function($httpProvider) {
$httpProvider.interceptors.push("httpInterceptor");
$httpProvider.interceptors.push("authInterceptor");
+ // Tell the BasicAuth plugin that we are Admin UI so it can serve us a 'Authorization: xBasic xxxx' header
+ // so that the browser will not intercept the login dialogue
+ $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
})
.directive('fileModel', function ($parse) {
return {