@@ -21,24 +21,22 @@ import java.io.IOException
21
21
import java .security .SecureRandom
22
22
import javax .security .sasl .AuthenticationException
23
23
import javax .servlet .ServletException
24
- import javax .servlet .http .Cookie
25
- import javax .servlet .http .HttpServletRequest
26
- import javax .servlet .http .HttpServletResponse
24
+ import javax .servlet .http .{Cookie , HttpServletRequest , HttpServletResponse }
27
25
import javax .ws .rs .core .NewCookie
28
26
29
27
import scala .collection .mutable
30
28
31
- import org .apache .commons .codec .binary .Base64
32
- import org .apache .commons .codec .binary .StringUtils
33
29
import org .apache .hadoop .hive .shims .Utils
34
30
import org .apache .thrift .TProcessor
35
31
import org .apache .thrift .protocol .TProtocolFactory
36
32
import org .apache .thrift .server .TServlet
37
33
38
34
import org .apache .kyuubi .Logging
39
35
import org .apache .kyuubi .config .KyuubiConf
36
+ import org .apache .kyuubi .server .http .authentication .AuthenticationFilter
37
+ import org .apache .kyuubi .server .http .authentication .AuthenticationHandler .AUTHORIZATION_HEADER
40
38
import org .apache .kyuubi .server .http .util .{CookieSigner , HttpAuthUtils , SessionManager }
41
- import org .apache .kyuubi .service .authentication .{ AuthenticationProviderFactory , KyuubiAuthenticationFactory }
39
+ import org .apache .kyuubi .service .authentication .KyuubiAuthenticationFactory
42
40
43
41
class ThriftHttpServlet (
44
42
processor : TProcessor ,
@@ -57,6 +55,7 @@ class ThriftHttpServlet(
57
55
private var isCookieSecure = false
58
56
private var isHttpOnlyCookie = false
59
57
private val X_FORWARDED_FOR_HEADER = " X-Forwarded-For"
58
+ private val authenticationFilter = new AuthenticationFilter (conf)
60
59
61
60
override def init (): Unit = {
62
61
isCookieAuthEnabled = conf.get(KyuubiConf .FRONTEND_THRIFT_HTTP_COOKIE_AUTH_ENABLED )
@@ -72,6 +71,7 @@ class ThriftHttpServlet(
72
71
isCookieSecure = conf.get(KyuubiConf .FRONTEND_THRIFT_HTTP_USE_SSL )
73
72
isHttpOnlyCookie = conf.get(KyuubiConf .FRONTEND_THRIFT_HTTP_COOKIE_IS_HTTPONLY )
74
73
}
74
+ authenticationFilter.initAuthHandlers()
75
75
}
76
76
77
77
@ throws[ServletException ]
@@ -105,10 +105,10 @@ class ThriftHttpServlet(
105
105
// If the cookie based authentication is not enabled or the request does not have a valid
106
106
// cookie, use authentication depending on the server setup.
107
107
if (clientUserName == null ) {
108
- clientUserName = doPasswdAuth (request, authFactory )
108
+ clientUserName = authenticate (request, response )
109
109
}
110
110
111
- assert (clientUserName != null )
111
+ require (clientUserName != null , " No valid authorization provided " )
112
112
debug(" Client username: " + clientUserName)
113
113
114
114
// Set the thread local username to be used for doAs if true
@@ -280,100 +280,10 @@ class ThriftHttpServlet(
280
280
newCookie + " ; HttpOnly"
281
281
}
282
282
283
- /**
284
- * Do the LDAP/PAM authentication
285
- *
286
- * @param request
287
- * @param authFactory
288
- * @throws AuthenticationException
289
- */
290
- @ throws[AuthenticationException ]
291
- private def doPasswdAuth (
292
- request : HttpServletRequest ,
293
- authFactory : KyuubiAuthenticationFactory ): String = {
294
- val userName = getUsername(request, authFactory : KyuubiAuthenticationFactory )
295
- debug(" Is No SASL Enabled : " + authFactory.isNoSaslEnabled)
296
- // No-op when authType is NOSASL
297
- if (authFactory.isNoSaslEnabled) return userName
298
- try {
299
- debug(" Initiating Password Authentication" )
300
- val password = getPassword(request, authFactory)
301
- val authMethod = authFactory.getValidPasswordAuthMethod
302
- debug(" Password Method: " + authMethod)
303
- val provider = AuthenticationProviderFactory .getAuthenticationProvider(authMethod, conf)
304
- debug(" Password Provider obtained" )
305
- provider.authenticate(userName, password)
306
- debug(" Password Provider authenticated username successfully" )
307
- } catch {
308
- case e : Exception =>
309
- throw new AuthenticationException (e.getMessage, e)
310
- }
311
- userName
312
- }
313
-
314
- @ throws[AuthenticationException ]
315
- private def getUsername (
316
- request : HttpServletRequest ,
317
- authFactory : KyuubiAuthenticationFactory ): String = {
318
- val creds = getAuthHeaderTokens(request, authFactory)
319
- // Username must be present
320
- if (creds(0 ) == null || creds(0 ).isEmpty) {
321
- throw new AuthenticationException (" Authorization header received " +
322
- " from the client does not contain username." )
323
- }
324
- creds(0 )
325
- }
326
-
327
- @ throws[AuthenticationException ]
328
- private def getPassword (
329
- request : HttpServletRequest ,
330
- authFactory : KyuubiAuthenticationFactory ): String = {
331
- val creds = getAuthHeaderTokens(request, authFactory)
332
- // Password must be present
333
- if (creds(1 ) == null || creds(1 ).isEmpty) {
334
- throw new AuthenticationException (" Authorization header received " +
335
- " from the client does not contain username." )
336
- }
337
- creds(1 )
338
- }
339
-
340
- @ throws[AuthenticationException ]
341
- private def getAuthHeaderTokens (
342
- request : HttpServletRequest ,
343
- authFactory : KyuubiAuthenticationFactory ): Array [String ] = {
344
- val authHeaderBase64 = getAuthHeader(request, authFactory)
345
- val authHeaderString = StringUtils .newStringUtf8(Base64 .decodeBase64(authHeaderBase64.getBytes))
346
- authHeaderString.split(" :" )
347
- }
348
-
349
- /**
350
- * Returns the base64 encoded auth header payload
351
- *
352
- * @param request
353
- * @param authFactory
354
- * @return
355
- * @throws AuthenticationException
356
- */
357
- @ throws[AuthenticationException ]
358
- private def getAuthHeader (
359
- request : HttpServletRequest ,
360
- authFactory : KyuubiAuthenticationFactory ): String = {
361
- val authHeader = request.getHeader(HttpAuthUtils .AUTHORIZATION )
362
- // Each http request must have an Authorization header
363
- if (authHeader == null || authHeader.isEmpty) {
364
- throw new AuthenticationException (" Authorization header received " +
365
- " from the client is empty." )
366
- }
367
-
368
- var authHeaderBase64String : String = null
369
- val beginIndex = (HttpAuthUtils .BASIC + " " ).length
370
- authHeaderBase64String = authHeader.substring(beginIndex)
371
- // Authorization header must have a payload
372
- if (authHeaderBase64String == null || authHeaderBase64String.isEmpty) {
373
- throw new AuthenticationException (" Authorization header received " +
374
- " from the client does not contain any data." )
375
- }
376
- authHeaderBase64String
283
+ private def authenticate (request : HttpServletRequest , response : HttpServletResponse ): String = {
284
+ val authorization = request.getHeader(AUTHORIZATION_HEADER )
285
+ authenticationFilter.getMatchedHandler(authorization).map(
286
+ _.authenticate(request, response)).orNull
377
287
}
378
288
379
289
private def getDoAsQueryParam (queryString : String ): String = {
0 commit comments