2013-11-22 84 views
0

我正在嘗試使用金字塔來實現基本的身份驗證和授權。我跟許多後像authentication with http header in 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我只是被禁止!不要求用戶或密碼!

我還需要什麼?

艾米的幫助深表感謝

感謝,

卡洛斯。

+0

我會用'config.add_forbidden_​​view(forbidden_​​view)做'(在'main'功能),以及在'forbidden_​​view'添加的挑戰頭。 –

+0

感謝Antonie的評論。你能指出我如何做到這一點的例子嗎? – QLands

回答

0

請參閱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