|
18 | 18 | */
|
19 | 19 | package org.apache.pulsar.broker.authentication;
|
20 | 20 |
|
| 21 | +import static org.apache.pulsar.broker.web.AuthenticationFilter.AuthenticatedDataAttributeName; |
| 22 | +import static org.apache.pulsar.broker.web.AuthenticationFilter.AuthenticatedRoleAttributeName; |
21 | 23 | import java.io.Closeable;
|
22 | 24 | import java.io.IOException;
|
23 | 25 | import java.util.ArrayList;
|
|
28 | 30 | import java.util.stream.Collectors;
|
29 | 31 | import javax.naming.AuthenticationException;
|
30 | 32 | import javax.servlet.http.HttpServletRequest;
|
| 33 | +import javax.servlet.http.HttpServletResponse; |
31 | 34 | import org.apache.commons.lang3.StringUtils;
|
32 | 35 | import org.apache.pulsar.broker.PulsarServerException;
|
33 | 36 | import org.apache.pulsar.broker.ServiceConfiguration;
|
34 | 37 | import org.apache.pulsar.broker.web.AuthenticationFilter;
|
| 38 | +import org.apache.pulsar.common.sasl.SaslConstants; |
35 | 39 | import org.slf4j.Logger;
|
36 | 40 | import org.slf4j.LoggerFactory;
|
37 | 41 |
|
@@ -85,16 +89,77 @@ public AuthenticationService(ServiceConfiguration conf) throws PulsarServerExcep
|
85 | 89 | }
|
86 | 90 | }
|
87 | 91 |
|
| 92 | + private String getAuthMethodName(HttpServletRequest request) { |
| 93 | + return request.getHeader(AuthenticationFilter.PULSAR_AUTH_METHOD_NAME); |
| 94 | + } |
| 95 | + |
| 96 | + private AuthenticationProvider getAuthProvider(String authMethodName) throws AuthenticationException { |
| 97 | + AuthenticationProvider providerToUse = providers.get(authMethodName); |
| 98 | + if (providerToUse == null) { |
| 99 | + throw new AuthenticationException( |
| 100 | + String.format("Unsupported authentication method: [%s].", authMethodName)); |
| 101 | + } |
| 102 | + return providerToUse; |
| 103 | + } |
| 104 | + |
| 105 | + public boolean authenticateHttpRequest(HttpServletRequest request, HttpServletResponse response) |
| 106 | + throws Exception { |
| 107 | + String authMethodName = getAuthMethodName(request); |
| 108 | + if (authMethodName == null |
| 109 | + && SaslConstants.SASL_TYPE_VALUE.equalsIgnoreCase(request.getHeader(SaslConstants.SASL_HEADER_TYPE))) { |
| 110 | + // This edge case must be handled because the Pulsar SASL implementation does not add the |
| 111 | + // X-Pulsar-Auth-Method-Name header. |
| 112 | + authMethodName = SaslConstants.AUTH_METHOD_NAME; |
| 113 | + } |
| 114 | + if (authMethodName != null) { |
| 115 | + AuthenticationProvider providerToUse = getAuthProvider(authMethodName); |
| 116 | + try { |
| 117 | + return providerToUse.authenticateHttpRequest(request, response); |
| 118 | + } catch (AuthenticationException e) { |
| 119 | + if (LOG.isDebugEnabled()) { |
| 120 | + LOG.debug("Authentication failed for provider " + providerToUse.getAuthMethodName() + " : " |
| 121 | + + e.getMessage(), e); |
| 122 | + } |
| 123 | + throw e; |
| 124 | + } |
| 125 | + } else { |
| 126 | + for (AuthenticationProvider provider : providers.values()) { |
| 127 | + try { |
| 128 | + return provider.authenticateHttpRequest(request, response); |
| 129 | + } catch (AuthenticationException e) { |
| 130 | + if (LOG.isDebugEnabled()) { |
| 131 | + LOG.debug("Authentication failed for provider " + provider.getAuthMethodName() + ": " |
| 132 | + + e.getMessage(), e); |
| 133 | + } |
| 134 | + // Ignore the exception because we don't know which authentication method is expected here. |
| 135 | + } |
| 136 | + } |
| 137 | + // No authentication provided |
| 138 | + if (!providers.isEmpty()) { |
| 139 | + if (StringUtils.isNotBlank(anonymousUserRole)) { |
| 140 | + request.setAttribute(AuthenticatedRoleAttributeName, anonymousUserRole); |
| 141 | + request.setAttribute(AuthenticatedDataAttributeName, new AuthenticationDataHttps(request)); |
| 142 | + return true; |
| 143 | + } |
| 144 | + // If at least a provider was configured, then the authentication needs to be provider |
| 145 | + throw new AuthenticationException("Authentication required"); |
| 146 | + } else { |
| 147 | + // No authentication required |
| 148 | + return true; |
| 149 | + } |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + /** |
| 154 | + * @deprecated use {@link #authenticateHttpRequest(HttpServletRequest, HttpServletResponse)} |
| 155 | + */ |
| 156 | + @Deprecated(since = "2.12.0") |
88 | 157 | public String authenticateHttpRequest(HttpServletRequest request, AuthenticationDataSource authData)
|
89 | 158 | throws AuthenticationException {
|
90 |
| - String authMethodName = request.getHeader(AuthenticationFilter.PULSAR_AUTH_METHOD_NAME); |
| 159 | + String authMethodName = getAuthMethodName(request); |
91 | 160 |
|
92 | 161 | if (authMethodName != null) {
|
93 |
| - AuthenticationProvider providerToUse = providers.get(authMethodName); |
94 |
| - if (providerToUse == null) { |
95 |
| - throw new AuthenticationException( |
96 |
| - String.format("Unsupported authentication method: [%s].", authMethodName)); |
97 |
| - } |
| 162 | + AuthenticationProvider providerToUse = getAuthProvider(authMethodName); |
98 | 163 | try {
|
99 | 164 | if (authData == null) {
|
100 | 165 | AuthenticationState authenticationState = providerToUse.newHttpAuthState(request);
|
@@ -140,10 +205,11 @@ public String authenticateHttpRequest(HttpServletRequest request, Authentication
|
140 | 205 | /**
|
141 | 206 | * Mark this function as deprecated, it is recommended to use a method with the AuthenticationDataSource
|
142 | 207 | * signature to implement it.
|
| 208 | + * @deprecated use {@link #authenticateHttpRequest(HttpServletRequest, HttpServletResponse)}. |
143 | 209 | */
|
144 | 210 | @Deprecated
|
145 | 211 | public String authenticateHttpRequest(HttpServletRequest request) throws AuthenticationException {
|
146 |
| - return authenticateHttpRequest(request, null); |
| 212 | + return authenticateHttpRequest(request, (AuthenticationDataSource) null); |
147 | 213 | }
|
148 | 214 |
|
149 | 215 | public AuthenticationProvider getAuthenticationProvider(String authMethodName) {
|
|
0 commit comments