'Forbidden' 使用 WSGI-Kerberos 的 运行 中间件时的响应

'Forbidden' response when running middleware with WSGI-Kerberos

对于网络应用程序,我正在使用 WSGI-Kerberos 编写一个中间件来处理身份验证。总的来说,这些努力旨在实施单点登录技术。因此,Active Directory 中 logged/active 的用户可以访问该应用程序。

我正在将我的网络应用程序部署到:

Linux TestServer 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64

这是我正在执行的一段代码:

from wsgiref.simple_server import make_server
from wsgi_kerberos import KerberosAuthMiddleware

def example(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello, %s' % environ['REMOTE_USER']]

if __name__ == '__main__':
    app = KerberosAuthMiddleware(example)
    http = make_server('0.0.0.0', 5000,  app)
    http.serve_forever()

但是,在浏览器中,我在打开 http://TestServer.l.s.d:5000/ link。有什么问题?

在 cmd 中我可以看到这个:

a.b.c.d - - [08/Jun/2021 07:44:43] "GET / HTTP/1.1" 401 12
a.b.c.d - - [08/Jun/2021 07:44:43] "GET / HTTP/1.1" 403 9

我已经将 'KRB5_KTNAME' 到 keytab 文件的位置集成到 os.environ['KRB5_KTNAME'] 中,如 export os.environ['KRB5_KTNAME']='/path/to/keytab/file.keytab'.

keytab 文件的内容如下所示:

ktutil:  list
slot KVNO Principal
---- ---- ---------------------------
   1    4 HTTP/TestServer.l.s.d@L.S.D

完成所有问题后 :

Does your keytab have the correct service principal name? Does your client system have Kerberos tickets for the user? (Does it have the initial 'krbtgt' ticket, and did it also obtain a ticket for your web app's SPN?)

观察到 keytab 文件有错误(arcfour-hmac 已弃用)encryption type.

再次生成了使用 aes256-cts-hmac-sha1-96 加密类型的新密钥表文件,现在它看起来像:

KVNO Timestamp Principal
---- ------------------- --------------------------------------------------
5 01/01/1970 01:00:00 HTTP/TestServer.l.s.d@L.S.D (aes256-cts-hmac-sha1-96)

此后再次测试,在这个阶段我得到了以下错误:

a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 401 12
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 200 0
Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 266, in write
    "write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('10.169.43.210', 58080)
Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 266, in write
    "write() argument must be a bytes instance"

AssertionError: write() argument must be a bytes instance

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 141, in run
    self.handle_error()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 368, in handle_error
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 274, in write
    self.send_headers()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 331, in send_headers
    if not self.origin_server or self.client_is_modern():
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 344, in client_is_modern
    return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.7/socketserver.py", line 720, in __init__
    self.handle()
  File "/usr/lib/python3.7/wsgiref/simple_server.py", line 133, in handle
    handler.run(self.server.get_app())
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 144, in run
    self.close()
  File "/usr/lib/python3.7/wsgiref/simple_server.py", line 35, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 403 9

在我发现的错误中:

AssertionError: write() argument must be a bytes instance

此后它把我带到了这个线程

然后适当编辑代码的内容:

from wsgiref.simple_server import make_server
from wsgi_kerberos import KerberosAuthMiddleware

def example(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    response_body = 'Hello, %s!' % environ['REMOTE_USER']
    return [response_body.encode()]

if __name__ == '__main__':
    app = KerberosAuthMiddleware(example)
    http = make_server('0.0.0.0', 5000,  app)
    http.serve_forever()

现在我可以在我的浏览器中这样做:

Hello, username@L.S.D!

其中 username 是我在 Windows 系统中的用户名。


参考文献:

  • Authentication issues with WWW-Authenticate: Negotiate