TypeError:运行FlaskKerberos时,参数1必须为字符串,而不是None
问题描述
我正在尝试使用有效的密钥表文件(it works with WSGI-Kerberos)运行Flask-Kerberos example。
这是我的‘example.py’文件的内容
from flask import Flask
from flask import render_template
from flask_kerberos import init_kerberos
from flask_kerberos import requires_authentication
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
@app.route("/")
@requires_authentication
def index(user):
return render_template('index.html', user=user)
if __name__ == '__main__':
init_kerberos(app)
app.run()
这里是‘config.py’
import os
import base64
from dotenv import load_dotenv
basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.flaskenv'))
class Config(object):
# Setup Secret Key for Application
SECRET_KEY = os.environ.get('SECRET_KEY') or str(base64.b64encode('you-will-never-guess'.encode("utf-8")))
# Location of the keytab file
KRB5_KTNAME = "K000007.keytab"
这里是‘.flaskenv’
FLASK_APP=example.py
FLASK_RUN_HOST="0.0.0.0"
FLASK_RUN_PORT=5000
FLASK_ENV=development
但是,当通过flask run
启动烧瓶时,我在CMD中收到以下错误:
(venv) Server@User:~/.../flask_kerberos_example$ flask run
* Serving Flask app "example.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 603-674-916
a.b.c.d - - [23/Jun/2021 08:47:51] "GET / HTTP/1.1" 401 -
a.b.c.d - - [23/Jun/2021 08:47:51] "GET / HTTP/1.1" 500 -
Traceback (most recent call last):
File "/venv/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/venv/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/venv/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/venv/lib/python3.7/site-packages/flask_kerberos.py", line 106, in decorated
rc = _gssapi_authenticate(token)
File "/venv/lib/python3.7/site-packages/flask_kerberos.py", line 70, in _gssapi_authenticate
rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
TypeError: argument 1 must be str, not None
a.b.c.d - - [23/Jun/2021 08:47:51] "GET /?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
a.b.c.d - - [23/Jun/2021 08:47:51] "GET /?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
a.b.c.d - - [23/Jun/2021 08:47:51] "GET /?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
a.b.c.d - - [23/Jun/2021 08:47:51] "GET /?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
a.b.c.d - - [23/Jun/2021 08:47:51] "GET /?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
和我看过一些相关主题(没有帮助):
- Flask_kerberos KrbError: ('Principal not found in keytab', -1)
- SSO with Kerberos
解决方案
我开始时将Flask-Kerberos code直接集成到我的‘Example.py’文件中,并使用一些print()
:
"""HERE GOES THE CONTENT OF flask_kerberos.py"""
import kerberos
from flask import Response
from flask import _request_ctx_stack as stack
from flask import make_response
from flask import request
from functools import wraps
from socket import gethostname
from os import environ
_SERVICE_NAME = None #_SERVICE_NAME = 'HTTP/l.s.d'
def init_kerberos(app, service='HTTP', hostname=gethostname()):
'''
Configure the GSSAPI service name, and validate the presence of the
appropriate principal in the kerberos keytab.
:param app: a flask application
:type app: flask.Flask
:param service: GSSAPI service name
:type service: str
:param hostname: hostname the service runs under
:type hostname: str
'''
global _SERVICE_NAME
_SERVICE_NAME = "%s@%s" % (service, hostname)
print(_SERVICE_NAME) #HTTP@Server.l.s.d
if 'KRB5_KTNAME' not in environ:
app.logger.warn("Kerberos: set KRB5_KTNAME to your keytab file")
else:
try:
principal = kerberos.getServerPrincipalDetails(service, hostname)
except kerberos.KrbError as exc:
app.logger.warn("Kerberos: %s" % exc.message[0])
else:
app.logger.info("Kerberos: server is %s" % principal)
def _unauthorized():
'''
Indicate that authentication is required
'''
return Response('Unauthorized', 401, {'WWW-Authenticate': 'Negotiate'})
def _forbidden():
'''
Indicate a complete authentication failure
'''
return Response('Forbidden', 403)
def _gssapi_authenticate(token):
'''
Performs GSSAPI Negotiate Authentication
On success also stashes the server response token for mutual authentication
at the top of request context with the name kerberos_token, along with the
authenticated user principal with the name kerberos_user.
@param token: GSSAPI Authentication Token
@type token: str
@returns gssapi return code or None on failure
@rtype: int or None
'''
state = None
ctx = stack.top
try:
rc, state = kerberos.authGSSServerInit(_SERVICE_NAME)
if rc != kerberos.AUTH_GSS_COMPLETE:
return None
rc = kerberos.authGSSServerStep(state, token)
if rc == kerberos.AUTH_GSS_COMPLETE:
ctx.kerberos_token = kerberos.authGSSServerResponse(state)
ctx.kerberos_user = kerberos.authGSSServerUserName(state)
return rc
elif rc == kerberos.AUTH_GSS_CONTINUE:
return kerberos.AUTH_GSS_CONTINUE
else:
return None
except kerberos.GSSError:
return None
finally:
if state:
kerberos.authGSSServerClean(state)
def requires_authentication(function):
'''
Require that the wrapped view function only be called by users
authenticated with Kerberos. The view function will have the authenticated
users principal passed to it as its first argument.
:param function: flask view function
:type function: function
:returns: decorated function
:rtype: function
'''
@wraps(function)
def decorated(*args, **kwargs):
header = request.headers.get("Authorization")
if header:
ctx = stack.top
token = ''.join(header.split()[1:])
rc = _gssapi_authenticate(token)
if rc == kerberos.AUTH_GSS_COMPLETE:
response = function(ctx.kerberos_user, *args, **kwargs)
response = make_response(response)
if ctx.kerberos_token is not None:
response.headers['WWW-Authenticate'] = ' '.join(['negotiate',
ctx.kerberos_token])
return response
elif rc != kerberos.AUTH_GSS_CONTINUE:
return _forbidden()
return _unauthorized()
return decorated
"""END OF THE flask_kerberos.py"""
from flask import Flask
from flask import render_template
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
@app.route("/")
@requires_authentication
def index(user):
return render_template('index.html', user=user)
if __name__ == '__main__':
init_kerberos(app, hostname='Server.l.s.d')
app.run()
如this answer中所述:
问题完全如错误消息所述-您已经告诉 Kerberos库从密钥表中获取服务主体,但 密钥表不包含服务主体条目。
因此,我决定检查几个变量及其值,即_SERVICE_NAME
和getServerPrincipalDetails(service, hostname)
。
首先我设置_SERVICE_NAME='L.S.D'
,在我的浏览器中收到‘禁止’响应后。以下是CMD中的输出:
(venv) Server@User:~/.../flask_kerberos_example$ flask run
* Serving Flask app "example.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 417-811-792
a.b.c.d - - [06/Jul/2021 11:01:06] "GET / HTTP/1.1" 401 -
a.b.c.d - - [06/Jul/2021 11:01:06] "GET / HTTP/1.1" 403 -
我通过Vim运行上述代码我收到以下消息:
Traceback (most recent call last):
File "example.py", line 34, in init_kerberos
principal = kerberos.getServerPrincipalDetails(service, hostname)
kerberos.KrbError: ('Cannot get sequence cursor from keytab', 2)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "example.py", line 140, in <module>
init_kerberos(app)
File "example.py", line 36, in init_kerberos
app.logger.warn("Kerberos: %s" % exc.message[0])
AttributeError: 'KrbError' object has no attribute 'message'
shell returned 1
这个问题将我进一步带到了GitHub上的this issue。其中作者声明:
不要紧,不管我如何解释代码,它都可以很好地工作 服务=&Q;HTTP&Q;和主机名=&Q;my.host.name&Q;。因此,我尝试调整
getServerPrincipalDetails(service, hostname)
函数的service
和hostname
变量。对我来说,测试它最方便的方式是:
import kerberos
service = 'HTTP'
hostname = 'Server.l.s.d'
try:
principal = kerberos.getServerPrincipalDetails(service, hostname)
except kerberos.KrbError as exc:
print("Kerberos: %s" % exc.message[0])
else:
print("Kerberos: server is %s" % principal)
因此,我得到了以下变量及其值
_SERVICE_NAME = None
service = 'HTTP'
hostname = 'Server.l.s.d'
在浏览器中收到回复后
烧瓶Kerberos示例
成功了,我想您是用户名@L.S.D.
和相应的CMD
HTTP@Server.l.s.d
* Serving Flask app "example" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
a.b.c.d - - [08/Jul/2021 13:02:18] "GET / HTTP/1.1" 401 -
a.b.c.d - - [08/Jul/2021 13:02:18] "GET / HTTP/1.1" 200 -
a.b.c.d - - [08/Jul/2021 13:02:18] "GET /static/style.css HTTP/1.1" 304 -
不幸的是,它仍然不能通过flask run
工作。这是一个新问题:Flask-Kerberos yields different results when running the code via "flask run" and with Vim
相关文章