簡體   English   中英

具有金字塔的基本HTTP授權(挑戰客戶端)?

[英]Basic HTTP Authorization (challenge client) with Pyramid?

我正在嘗試使用金字塔實現基本的身份驗證和授權。 我跟隨許多帖子,例如在金字塔中使用HTTP標頭進行身份驗證

我只需要例如,如果用戶請求類似http://myserser.my:6543/private的服務器,服務器將挑戰客戶端,瀏覽器將詢問我用戶名和密碼(瀏覽器生成的典型用戶/密碼彈出窗口)然后在提供憑據后,應用程序將對其進行檢查並返回被禁止的內容。

這是我的代碼:

--init--.py

from pyramid.config import Configurator
from getdata.basic_authentication import BasicAuthenticationPolicy, mycheck
from pyramid.authorization import ACLAuthorizationPolicy

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    #config = Configurator(settings=settings)
    config = Configurator(root_factory='getdata.models.RootFactory', 
                          settings=settings,
                          authentication_policy=BasicAuthenticationPolicy(mycheck), 
                          authorization_policy=ACLAuthorizationPolicy(),
                          )

    config.include('pyramid_chameleon')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.add_route('private', '/private')
    config.scan()
    return config.make_wsgi_app()

views.py

from pyramid.security import authenticated_userid
from pyramid.view import view_config


@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
    return {'project': 'getdata'}

@view_config(route_name='private',  permission='dbauth')
def my_priavate_view(request):
    resp = Response('ok', content_type='text', charset='utf8')
    return resp

model.py(我只有一組dbauth)

from pyramid.security import Allow

    class RootFactory(object):
        __acl__ = [ (Allow, 'group:dbauth', 'dbauth')]                
        def __init__(self, request):
            pass

basic_authentication.py

import binascii

from zope.interface import implements

from paste.httpheaders import AUTHORIZATION
from paste.httpheaders import WWW_AUTHENTICATE

from pyramid.interfaces import IAuthenticationPolicy
from pyramid.security import Everyone
from pyramid.security import Authenticated
import yaml

def mycheck(credentials, request):
    login = credentials['login']
    password = credentials['password']

    print(login)
    print(password)

    USERS = {'user1':'pass1',
      'user2':'pass2'}
    GROUPS = {'user1':['group:viewers'],
          'user2':['group:editors']}

    if login in USERS and USERS[login] == password:
        return GROUPS.get(login, [])
    else:
        return None


def _get_basicauth_credentials(request):
    authorization = AUTHORIZATION(request.environ)
    try:
        authmeth, auth = authorization.split(' ', 1)
    except ValueError: # not enough values to unpack
        return None
    if authmeth.lower() == 'basic':
        try:
            auth = auth.strip().decode('base64')
        except binascii.Error: # can't decode
            return None
        try:
            login, password = auth.split(':', 1)
        except ValueError: # not enough values to unpack
            return None
        return {'login':login, 'password':password}

    return None

class BasicAuthenticationPolicy(object):
    """ A :app:`Pyramid` :term:`authentication policy` which
    obtains data from basic authentication headers.

    Constructor Arguments

    ``check``

        A callback passed the credentials and the request,
        expected to return None if the userid doesn't exist or a sequence
        of group identifiers (possibly empty) if the user does exist.
        Required.

    ``realm``

        Default: ``Realm``.  The Basic Auth realm string.

    """
    implements(IAuthenticationPolicy)

    def __init__(self, check, realm='Realm'):
        self.check = check
        self.realm = realm

    def authenticated_userid(self, request):
        credentials = _get_basicauth_credentials(request)
        if credentials is None:
            return None
        userid = credentials['login']
        if self.check(credentials, request) is not None: # is not None!
            return userid

    def effective_principals(self, request):
        effective_principals = [Everyone]
        credentials = _get_basicauth_credentials(request)
        if credentials is None:
            return effective_principals
        userid = credentials['login']
        groups = self.check(credentials, request)
        if groups is None: # is None!
            return effective_principals
        effective_principals.append(Authenticated)
        effective_principals.append(userid)
        effective_principals.extend(groups)
        return effective_principals

    def unauthenticated_userid(self, request):
        creds = self._get_credentials(request)
        if creds is not None:
            return creds['login']
        return None

    def remember(self, request, principal, **kw):
        return []

    def forget(self, request):
        head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
        return head

但是當我訪問http://myserser.my:6543/private時,我就被禁止了! 無需輸入用戶名或密碼!!

我還需要什么?

艾米的幫助深表感謝

謝謝,

卡洛斯

請參閱BasicAuthenticationPolicy文檔下的“發出挑戰”部分-瀏覽器在沒有挑戰的情況下不會提示輸入憑據。 嘗試按所述添加一個forbidden_view_config視圖(示例來自下面粘貼的鏈接)。

from pyramid.httpexceptions import HTTPUnauthorized
from pyramid.security import forget
from pyramid.view import forbidden_view_config

@forbidden_view_config()
def basic_challenge(request):
    response = HTTPUnauthorized()
    response.headers.update(forget(request))
    return response

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM