I am using the python requests library to intereact with an api.
I am first authenticating, getting a session-id and then creating a request session to persist that connection.
So I created a class to do this, but every time I use the class I am reinitialising and doing the authentication again. Which I want to avoid.
Essentially I created an API between the API I am calling using DRF.
How can I ensure that only 1 authenticated session is used across the entire app and that it persists through multiple request?
The class:
class RestClient:
session = None
def create_rest_client(self):
auth = requests.auth.HTTPBasicAuth(
USERNAME,
PASSWORD
)
response = requests.post(
f'https://{ settings.HOST }/rest/session',
auth=auth
)
session = requests.Session()
session_id = response.json().get('value')
session.headers.update({'api-session-id': session_id})
return session
def get_rest_client(self):
if self.session:
return self.session
else:
return self.create_rest_client()
Using the class I instantiate and get the client (naturally redoing the auth). I think this should either be global or a singleton.
Using class:
class ProductDetail(APIView):
def get(self, request, format=None, **kwargs):
response = []
rest_client = RestClient()
session = rest_client.get_rest_client()
response = session.get(
....use authenticated session
)
return Response(response.json())
I'd wire up a property like this:
class RestClient:
_session = None
#property
def session(self):
if self._session:
return self._session
auth = requests.auth.HTTPBasicAuth(USERNAME, PASSWORD)
response = requests.post(
f"https://{ settings.HOST }/rest/session", auth=auth
)
session = requests.Session()
session_id = response.json().get("value")
session.headers.update({"api-session-id": session_id})
self._session = session
return session
Now you can simply do client.session and it will be set up on the first access and reused thereafter.
EDIT: To persist this between RestClient instances, change references to self._session to RestClient._session.
Related
I'm using Falcon, I need pass variable from middleware to resource, how can I do that?
main.py
app = falcon.API(middleware=[
AuthMiddleware()
])
app.add_route('/', Resource())
and auth
class AuthMiddleware(object):
def process_request(self, req, resp):
self.vvv = True
and resource
class Resource(object):
def __init__(self):
self.vvv = False
def on_get(self, req, resp):
logging.info(self.vvv) #vvv is always False
why self.vvv is always false? I have changed it in middleware to true.
First of all you are confussing what self means. Self affects only to the instance of the class, is a way of adding attributes to your class, therefore your self.vvv in AuthMiddleware is a complete different attribute from your self.vvv in your class Resource.
Second, you do not need to know anything from AuthMiddleware in your resource, thats why you want to use middleware. Middleware is a way to execute logic after or before each request. You need to implement your middleware so it raises Falcon exceptions or either modifies your request or response.
For example, if you don't authorize a request, you must raise an exception like this:
class AuthMiddleware(object):
def process_request(self, req, resp):
token = req.get_header('Authorization')
challenges = ['Token type="Fernet"']
if token is None:
description = ('Please provide an auth token '
'as part of the request.')
raise falcon.HTTPUnauthorized('Auth token required',
description,
challenges,
href='http://docs.example.com/auth')
if not self._token_is_valid(token):
description = ('The provided auth token is not valid. '
'Please request a new token and try again.')
raise falcon.HTTPUnauthorized('Authentication required',
description,
challenges,
href='http://docs.example.com/auth')
def _token_is_valid(self, token):
return True # Suuuuuure it's valid...
Check Falcon page examples.
From https://falcon.readthedocs.io/en/stable/api/middleware.html:
In order to pass data from a middleware function to a resource function use the req.context and resp.context objects. These context objects are intended to hold request and response data specific to your app as it passes through the framework.
class AuthMiddleware(object):
def process_request(self, req, resp):
# self.vvv = True # -
req.context.vvv = True # +
class Resource(object):
# def __init__(self): # -
# self.vvv = False # -
def on_get(self, req, resp):
# logging.info(self.vvv) # -
logging.info(req.context.vvv) # +
You should not use the attributes on middleware and resource instances for your request data. Since you only instantiate them once, modifying their attributes is generally not thread-safe.
I'm learning how to implement user login in GAE following the instruction in http://gosurob.com/post/20024043690/gaewebapp2accounts.
Below is a portion of the code that creates a user aware handler that my other handlers are supposed to inherit. This allows me to simply return user info by self.user. Now my question is how do I retrieve the user info in a ndb class which obviously inherits ndb.Model rather than BaseHandler. Please advise. Thanks!
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
#super(BaseHandler,self).dispatch()
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def auth(self):
return auth.get_auth(request=self.request)
#webapp2.cached_property
def user(self):
user = self.auth.get_user_by_session()
return user
#webapp2.cached_property
def user_model(self):
user_model, timestamp = self.auth.store.user_model.get_by_auth_token(
self.user['user_id'],
self.user['token']) if self.user else (None, None)
return user_model
class Global_Var(ndb.Model): #<<< This is the ndb class from which I want to use the user info.
current_user = ndb.StringProperty()
#staticmethod
def get_id():
return user['email'] #<<< This, of course, errors out since user is not defined in this class
I'm trying to implement a decorator that authenticates the user's token before granting access to a function. My current implementation is kind of wonky in that I need to do two queries since I can't get locals in the decorator. Is there a better way to do this?
def require_auth(func):
print 'require_auth'
#wraps(func)
def inner():
if 'token' in request.json:
token = request.json['token']
session = Session()
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==token):
auth_user = instance.username
try:
auth_user
print 'authenticated!'
except NameError:
abort(401)
else:
abort(401)
return func()
return inner
#app.route('/st/projects', methods=['POST'])
#require_auth
def post_project():
session = Session()
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==request.json['token']):
auth_user = instance.username
# do something with auth_user
session.close()
You can store your authenticated user in flask.g:
from flask import g
# ...
def require_auth(func):
# ...
for instance in session.query(SQLTypes.User).filter(SQLTypes.User.token==token):
g.auth_user = instance.username
try:
g.auth_user
print 'authenticated!'
except AttributeError:
abort(401)
# ...
Then in your view function you can access the user as g.auth_user.
I am new to Python and MongoDB environment. I am implementing a small application in Python with Tornado + MongoDB. I want to store sessions in mongoDB.
In server.py
import os
import tornado.web
import tornado.ioloop
import settings
application = tornado.web.Application(
settings.urls,
my_template_path,
my_static_path
)
if __nam__ == '__main__':
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
In settings.py
import handler as H
urls = [
(r"/", H.ShowHome),
(r"/login", H.ShowLogin),
(r"/dashboard", H.ShowDashboard)
]
In handler.py
import os
# import session or some library ????
class ShowHome(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.SESSION = True or False based on session cookie
def get(self):
if not self.SESSION:
self.redirect('/login')
else:
self.render('index.html')
class ShowLogin(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.SESSION = True or False based on session cookie
def get(self):
if self.SESSION:
self.redirect('/dashboard')
else:
self.render('login.html')
class ShowDashboard(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.session = True or False based on session cookie
def get(self):
if not SESSION:
self.redirect('/login')
else:
self.render('dashboard.html')
In handlers I want to check session, how do I do this?
Do you mean something like this?
class Base(tornado.web.RequestHandler):
def get_unique_id(self):
return self.get_secure_cookie('unique_id')
def set_unique_id(self, some_value):
return self.set_secure_cookie('unique_id', some_value)
class ShowLogin(Base):
def get(self):
if get_unique_id():
# Get stuff from Mongo using unique_id
# mongo calls
self.redirect('/dashboard')
else:
self.render('login.html')
class LoginLogin(Base):
def post(self):
self.set_unique_id(some_id)
You probably dont want to do this though - Let Tornado handle if someone is logged in or out with the authenticated decorator
And unless you are holding a lot of data or very sensitive data it's normal (and easier) to put session data in the cookies
How I store an instance of a connection in twisted.web? I have seen request.getSession() but I searched and there are very few examples of how it is stored and retrieved later.
Thanks.
Update:
I want to store the ldap connection in a session for retrieve later
def render_POST(self, request):
command = request.path[1:]
session = request.getSession()
if command == "authentication":
Connect = LdapConnection(request.args['host'][0],request.args['user'][0],request.args['password'][0])
session.addComponent(LdapConnection, Connect)
if command == "users":
Connect = session.getComponent(LdapConnection)
u = Users(Connect, request.args['name'][0],request.args['employeeNumber'])
return
There are plenty of examples in the documentation of twisted. If you prefer a quick summary on how to use sessions.
from twisted.web.resource import Resource
class ShowSession(Resource):
def render_GET(self, request):
return 'Your session id is: ' + request.getSession().uid
class ExpireSession(Resource):
def render_GET(self, request):
request.getSession().expire()
return 'Your session has been expired.'
resource = ShowSession()
resource.putChild("expire", ExpireSession())
Do not forget that request.getsession() will create the session if it doesn't already exists. This tutorial explains how to store objects in session.
cache()
from zope.interface import Interface, Attribute, implements
from twisted.python.components import registerAdapter
from twisted.web.server import Session
from twisted.web.resource import Resource
class ICounter(Interface):
value = Attribute("An int value which counts up once per page view.")
class Counter(object):
implements(ICounter)
def __init__(self, session):
self.value = 0
registerAdapter(Counter, Session, ICounter)
class CounterResource(Resource):
def render_GET(self, request):
session = request.getSession()
counter = ICounter(session)
counter.value += 1
return "Visit #%d for you!" % (counter.value,)
resource = CounterResource()