我正在尝试使用金字塔实现基本身份验证和授权。我跟随了许多帖子,如authentication with http header in pyramid
我只需要例如,如果用户请求类似http://myserser.my:6543/private的内容,服务器将挑战客户端,浏览器将询问我用户和密码(浏览器生成的典型用户/密码弹出窗口)然后给出应用程序将检查它们的凭据并返回禁止的内容。
这是我的代码:
- 初始化 - 吡
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 :(得分: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