2013-11-22 56 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