【问题标题】:Flask-HTTPAuth verify_password function not receiving username or passwordFlask-HTTPAuth verify_password 函数未接收用户名或密码
【发布时间】:2015-05-15 11:22:04
【问题描述】:

当我尝试使用 @auth.login_required 装饰器访问路由时,系统会提示我输入用户名和密码。输入此信息后,verify_password 函数的参数username_or_tokenpassword''。为什么数据是空的?

@auth.verify_password
def verify_password(username_or_token, password):
    # first try to authenticate by token
    user = USER.verify_auth_token(username_or_token)
    logger.debug("user = %r", user)
    logger.debug("Entered USEREMAIL = %r" ,  username_or_token)
    logger.debug("entered password = %r" ,  password)

    if not user:
        # try to authenticate with username/password
        user = session.query(USER).filter_by(USEREMAIL=username_or_token).first()   
        if not user or not user.verify_password(password):
            return False
    g.user = user
    return True

更新

我已将代码简化为:

@auth.verify_password
def verify_password(username, password):
    logger.debug("username = %s" % username)
    logger.debug("password = %s" % password)
    return true


@app.route('/api/token')
@auth.login_required
def get_auth_token():
    return "Hello, %s!" % auth.username()

我正在使用Advanced Rest Client 测试此功能。

http://localhost:8081/myapp/api/token

我还附上了一个Authorization 标头。

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Authorization: Basic YXNkOmFzZA==
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4

这导致输出:

Hello, !

日志文件:

username = 
password = 

我也不再被提示输入我的security credentials

另一个奇怪的是,即使我将verify_password 中的返回更改为false,我仍然得到相同的输出:Hello, !

【问题讨论】:

  • 如果您提供一个重现问题的完整示例,将会很有帮助。仅当客户端不发送 Authorization 标头时,用户名和密码才设置为空字符串,因此这可能是客户端问题。

标签: python flask http-authentication flask-httpauth


【解决方案1】:

我的经历与 OP 类似。如果您使用 mod_wsgi 运行,请确保将 WSGIPassAuthorization On 设置为 documented here

【讨论】:

    【解决方案2】:

    我能够通过这个最小的示例获取用户名和密码:

    from flask import Flask
    from flask.ext.httpauth import HTTPBasicAuth
    
    app = Flask(__name__)
    auth = HTTPBasicAuth()
    
    @auth.verify_password
    def foo(username, password):
        print "verifying...."
        print username
        print password
        return False
    
    @app.route('/')
    @auth.login_required
    def index():
        return "Hello, %s!" % auth.username()
    
    if __name__ == '__main__':
        app.run()
    

    但是,在处理它时,chrome 保存了 cookie,我不得不删除所有缓存,包括 cookie,因为我正在自动进行身份验证。也许这会给你带来麻烦。

    另外,不要忘记用@auth.login_required 装饰器标记@app.route("/")。否则,不会调用 verify_password 回调。

    【讨论】:

    • 它还有助于添加一个向此类应用程序提交数据的示例 HTML 表单。
    【解决方案3】:

    在 EC2 上运行我的 Flask 应用程序时遇到了同样的问题。所以我猜你是在 wsgi 服务后面运行你的应用程序。 关键是 wsgi 会为了不同的目的拦截每个请求头,所以我们需要做一些配置来确保身份验证头在到达我们的应用程序之前是完整的。 感谢 Erik Stephens 的回答帮助我解决了这个问题。我将 WSGIPassAuthorization On 放到我的 EC2 实例上的 /etc/httpd/conf.d/wsgi.conf 并重新启动 httpd 服务。你们可能希望仅针对您的应用程序 wsgi 配置文件进行更新,直至您的配置。 希望这可以帮助在将应用程序启动到 aws 时遇到同样问题的人。

    【讨论】:

      【解决方案4】:

      如果您允许用户,则@verify_password 回调应返回True,否则应返回False。在此函数中,匿名用户(即不发送身份验证的用户)在 usernamepassword 字段中均用空字符串表示。

      在您的代码中,您没有验证用户凭据是否有效。相反,尝试这样的事情:

      @auth.verify_password
      def verify_password(username, password):
          logger.debug("username = %s" % username)
          logger.debug("password = %s" % password)
          if username == '':
              return False
          return true
      

      以上将允许用户名/密码的任意组合,但不允许匿名用户进入。

      【讨论】:

      • 谢谢@Miguel。使用它确实会阻止匿名用户。但是,username'' 时,我仍然遇到同样的问题。这就是我发送请求的方式(需要 Chrome Advanced Rest Client):chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo/RestClient.html#RequestPlace:default。当我发送此邮件时,系统会提示我 authorisation 屏幕。无论我在这里输入什么然后单击Log In,该框都会不断重新出现。当我最终按下Cancel 时,我收到了Unauthorised Access 的消息。
      • @Giri:这是浏览器的行为,只要服务器响应 401 状态代码,浏览器就会显示登录对话框。避免这种情况的一种简单方法是返回 403 状态代码而不是 401。您可以在 Flask-HTTPAuth 错误处理程序中执行此操作。
      【解决方案5】:

      基本身份验证示例。此示例演示如何使用安全散列密码通过基本身份验证保护 Flask 端点。运行此示例后,在浏览器中访问 http://localhost:5000。要获得访问权限,您可以使用 (username=john, password=hello) 或 (username=susan, password=bye)。

      from flask import Flask 
      from flask_httpauth import HTTPBasicAuth 
      from werkzeug.security import generate_password_hash, check_password_hash
      
      app = Flask(name) 
      auth = HTTPBasicAuth()
      
      users = { "john": generate_password_hash("hello"), "susan": generate_password_hash("bye") }
      
      @auth.verify_password 
      def verify_password(username, password): 
          if username in users: return check_password_hash(users.get(username), password) 
          else: return False
      
      @app.route('/') 
      @auth.login_required def index(): 
          return "Hello, %s!" % auth.username()
      
      if name == 'main': 
          app.run(debug=True, host='0.0.0.0')
      

      【讨论】:

      • 你可能想要格式化代码,尤其是对于 python。
      猜你喜欢
      • 2015-09-25
      • 2014-09-22
      • 2018-06-12
      • 2014-11-27
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      • 2012-07-13
      相关资源
      最近更新 更多