Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In the end it became clear how to use authentication and authorization. Everything was actually written I just didn't catch the concept at once. I'll try to write how I got it working explaining in a noobish way, which I had to explain it to myself. I hope it will be useful to someone. Sources in the end may help to understand my writing ;) All comments are welcome. If I got something wrong, please correct me.</p> <h2>Authentication</h2> <p>Most important is the <a href="http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/auth/basic.html" rel="nofollow noreferrer">basic authentication</a> in which BasicAuthenticationPolicy must have methods that can be used later in pyramid application - like authenticated_userid(request). These methods use _get_basicauth_credentials() which pulls out login and password that were passed in http header. The actual checking if the login and password are correct happens in mycheck().</p> <p>Now in __init__.py we must add BasicAuthenticationPolicy with method mycheck as an argument to our application configurator, so the pyramid can use it.</p> <p>In a matter of authentication that is all. Now you should be able if and who was authenticated using authenticated_userid(request) (see views.py)</p> <h2>Authorization</h2> <p>To use pyramid authorization to resources we need to add ACLAuthorizationPolicy to our configurator in __init__.py and add __acl__ to the resources. In most simple case to the root_factory (see <a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki2/authorization.html#adding-a-root-factory" rel="nofollow noreferrer">this</a> and <a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html#assigning-acls" rel="nofollow noreferrer">this</a>) ACL defines which group has what permission. If I'm not mistaken in (Allow, 'group:viewers', 'view') 'group:viewers' has to be what authentication method - mycheck() - returns. </p> <p>The last step in authorization is add permission to certain view using a decorator (or in add_route). If we add the ACL permission - view - to a view_page then group:viewers is allowed to see that page (call view_page). </p> <p>basic_authentication.py</p> <pre><code>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'] 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 </code></pre> <p>myproject.__init__.py</p> <pre><code>from pyramid.config import Configurator from myproject.resources import Root from myproject.basic_authentication import BasicAuthenticationPolicy, mycheck from pyramid.authorization import ACLAuthorizationPolicy def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ config = Configurator(root_factory='myproject.models.RootFactory', settings=settings, authentication_policy=BasicAuthenticationPolicy(mycheck), authorization_policy=ACLAuthorizationPolicy(), ) config.add_static_view('static', 'myproject:static', cache_max_age=3600) config.add_route('view_page', '/view') config.add_route('edit_page', '/edit') config.scan() app = config.make_wsgi_app() return app </code></pre> <p>models.py</p> <pre><code>from pyramid.security import Allow class RootFactory(object): __acl__ = [ (Allow, 'group:viewers', 'view'), (Allow, 'group:editors', 'edit') ] def __init__(self, request): pass </code></pre> <p>views.py</p> <pre><code>from pyramid.security import authenticated_userid from pyramid.view import view_config #def my_view(request): # return render_to_response('templates/simple.pt', {}) @view_config(route_name='view_page', renderer='templates/view.pt', permission='view') def view_page(request): return {} @view_config(route_name='edit_page', renderer='templates/edit.pt', permission='edit') def edit_page(request): return {} </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload