Rewrite 'simple example' in docs, added it to demo dir (#154)

This commit is contained in:
Patryk Lorenowicz 2018-04-26 11:15:12 +02:00 committed by Andrew Svetlov
parent 27ffe6dc3c
commit f8dcc4a6de
2 changed files with 175 additions and 49 deletions

View File

@ -0,0 +1,93 @@
from aiohttp import web
from aiohttp_session import SimpleCookieStorage, session_middleware
from aiohttp_security import has_permission, \
is_anonymous, remember, forget, \
setup as setup_security, SessionIdentityPolicy
from aiohttp_security.abc import AbstractAuthorizationPolicy
# Demo authorization policy for only one user.
# User 'jack' has only 'listen' permission.
# For more complicated authorization policies see examples
# in the 'demo' directory.
class SimpleJack_AuthorizationPolicy(AbstractAuthorizationPolicy):
async def authorized_userid(self, identity):
"""Retrieve authorized user id.
Return the user_id of the user identified by the identity
or 'None' if no user exists related to the identity.
"""
if identity == 'jack':
return identity
async def permits(self, identity, permission, context=None):
"""Check user permissions.
Return True if the identity is allowed the permission
in the current context, else return False.
"""
return identity == 'jack' and permission in ('listen',)
async def handler_root(request):
is_logged = not await is_anonymous(request)
return web.Response(text='''<html><head></head><body>
Hello, I'm Jack, I'm {logged} logged in.<br /><br />
<a href="/login">Log me in</a><br />
<a href="/logout">Log me out</a><br /><br />
Check my permissions,
when i'm logged in and logged out.<br />
<a href="/listen">Can I listen?</a><br />
<a href="/speak">Can I speak?</a><br />
</body></html>'''.format(
logged='' if is_logged else 'NOT',
), content_type='text/html')
async def handler_login_jack(request):
redirect_response = web.HTTPFound('/')
await remember(request, redirect_response, 'jack')
raise redirect_response
async def handler_logout(request):
redirect_response = web.HTTPFound('/')
await forget(request, redirect_response)
raise redirect_response
@has_permission('listen')
async def handler_listen(request):
return web.Response(body="I can listen!")
@has_permission('speak')
async def handler_speak(request):
return web.Response(body="I can speak!")
async def make_app():
#
# WARNING!!!
# Never use SimpleCookieStorage on production!!!
# Its highly insecure!!!
#
# make app
middleware = session_middleware(SimpleCookieStorage())
app = web.Application(middlewares=[middleware])
# add the routes
app.router.add_route('GET', '/', handler_root)
app.router.add_route('GET', '/login', handler_login_jack)
app.router.add_route('GET', '/logout', handler_logout)
app.router.add_route('GET', '/listen', handler_listen)
app.router.add_route('GET', '/speak', handler_speak)
# set up policies
policy = SessionIdentityPolicy()
setup_security(app, policy, SimpleJack_AuthorizationPolicy())
return app
if __name__ == '__main__':
web.run_app(make_app(), port=9000)

View File

@ -7,63 +7,96 @@ How to Make a Simple Server With Authorization
Simple example::
import asyncio
from aiohttp import web
async def root_handler(request):
text = "Alive and kicking!"
return web.Response(body=text.encode('utf-8'))
# option 2: auth at a higher level?
# set user_id and allowed in the wsgi handler
@protect('view_user')
async def user_handler(request):
name = request.match_info.get('name', "Anonymous")
text = "Hello, " + name
return web.Response(body=text.encode('utf-8'))
from aiohttp_session import SimpleCookieStorage, session_middleware
from aiohttp_security import has_permission, \
is_anonymous, remember, forget, \
setup as setup_security, SessionIdentityPolicy
from aiohttp_security.abc import AbstractAuthorizationPolicy
# option 3: super low
# wsgi doesn't do anything
async def user_update_handler(request):
# identity, asked_permission
user_id = await identity_policy.identify(request)
identity = await auth_policy.authorized_userid(user_id)
allowed = await request.auth_policy.permits(
identity, asked_permission)
if not allowed:
# how is this pluggable as well?
# ? return NotAllowedStream()
raise NotAllowedResponse()
# Demo authorization policy for only one user.
# User 'jack' has only 'listen' permission.
# For more complicated authorization policies see examples
# in the 'demo' directory.
class SimpleJack_AuthorizationPolicy(AbstractAuthorizationPolicy):
async def authorized_userid(self, identity):
"""Retrieve authorized user id.
Return the user_id of the user identified by the identity
or 'None' if no user exists related to the identity.
"""
if identity == 'jack':
return identity
update_user()
async def permits(self, identity, permission, context=None):
"""Check user permissions.
Return True if the identity is allowed the permission
in the current context, else return False.
"""
return identity == 'jack' and permission in ('listen',)
async def init(loop):
# set up identity and auth
auth_policy = DictionaryAuthorizationPolicy({'me': ('view_user',),
'you': ('view_user',
'edit_user',)})
identity_policy = CookieIdentityPolicy()
auth = authorization_middleware(auth_policy, identity_policy)
# wsgi app
app = web.Application(loop=loop, middlewares=*auth)
async def handler_root(request):
is_logged = not await is_anonymous(request)
return web.Response(text='''<html><head></head><body>
Hello, I'm Jack, I'm {logged} logged in.<br /><br />
<a href="/login">Log me in</a><br />
<a href="/logout">Log me out</a><br /><br />
Check my permissions,
when i'm logged in and logged out.<br />
<a href="/listen">Can I listen?</a><br />
<a href="/speak">Can I speak?</a><br />
</body></html>'''.format(
logged='' if is_logged else 'NOT',
), content_type='text/html')
async def handler_login_jack(request):
redirect_response = web.HTTPFound('/')
await remember(request, redirect_response, 'jack')
raise redirect_response
async def handler_logout(request):
redirect_response = web.HTTPFound('/')
await forget(request, redirect_response)
raise redirect_response
@has_permission('listen')
async def handler_listen(request):
return web.Response(body="I can listen!")
@has_permission('speak')
async def handler_speak(request):
return web.Response(body="I can speak!")
async def make_app():
#
# WARNING!!!
# Never use SimpleCookieStorage on production!!!
# Its highly insecure!!!
#
# make app
middleware = session_middleware(SimpleCookieStorage())
app = web.Application(middlewares=[middleware])
# add the routes
app.router.add_route('GET', '/', root_handler)
app.router.add_route('GET', '/{user}', user_handler)
app.router.add_route('GET', '/{user}/edit', user_update_handler)
app.router.add_route('GET', '/', handler_root)
app.router.add_route('GET', '/login', handler_login_jack)
app.router.add_route('GET', '/logout', handler_logout)
app.router.add_route('GET', '/listen', handler_listen)
app.router.add_route('GET', '/speak', handler_speak)
# get it started
srv = await loop.create_server(app.make_handler(),
'127.0.0.1', 8080)
print("Server started at http://127.0.0.1:8080")
return srv
# set up policies
policy = SessionIdentityPolicy()
setup_security(app, policy, SimpleJack_AuthorizationPolicy())
return app
loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
try:
loop.run_forever()
except KeyboardInterrupt:
pass # TODO put handler cleanup here
if __name__ == '__main__':
web.run_app(make_app(), port=9000)