Pyramid.security: Does user information from a database with unauthenticated_userid (request) get really secure?

I am trying to make an accessible cache of user data using the Pyramid doc " Creating a" User Object "accessible as an example request attribute .

They use this code to return the user object in set_request_property:

from pyramid.security import unauthenticated_userid def get_user(request): # the below line is just an example, use your own method of # accessing a database connection here (this could even be another # request property such as request.db, implemented using this same # pattern). dbconn = request.registry.settings['dbconn'] userid = unauthenticated_userid(request) if userid is not None: # this should return None if the user doesn't exist # in the database return dbconn['users'].query({'id':userid}) 

I don’t understand why they use unauthenticated_userid (query) to search for user information from the database ... is it unsafe? This means that the user may not be logged in, so why do you use this identifier to get personal information from the database?

Should not

  userid = authenticated_userid(request) 

to make sure the user is logged in? What is the advantage of using unauthenticated_userid (request)? Please help me understand what is happening here.

+4
source share
3 answers

The unauthenticated_userid call is a cheaper call; it searches for the user ID from the request without having to go through the entire authentication process again.

The key concept is the word again. You should use only the method that is already allowed. In other words, by the time you reach the code using unauthenticated_userid , you have already verified the user and, in particular, you do not want to do this again for this particular call.

Authenticating users to persistent storage can be expensive, especially if the storage does not support caching. The unauthenticated_userid API unauthenticated_userid is an optimization where the request is basically a userid cache.

+3
source

This is a late answer, but it has been linked as a source of confusion for some Pyramid users.

The accepted answer here is not the actual reason that unauthenticated_userid used for request.user . This has nothing to do with performance.

The reason it uses unauthenticated_userid is because it makes it easy to reuse the authentication policy between applications with the required smaller changes. Your application needs a “source of truth” in order to allow the user to be considered authenticated, and, as a rule, the internal logic of the policy is not enough to make this determination. The correct cookie is good, but you usually want to check it with the backend before trusting it. Great, so where do we put this logic? Well, unauthenticated_userid does not make sense because it is a reusable piece of policy that specifically focuses on parsing request headers. You can put it in authenticated_userid , but this method is not the one you usually need in your application. Usually you use request.user in your applications (rarely, you probably take care of request.authenticated_userid directly), and finally request.user is a superset of functionality - it provides an entire user object, not just an identifier. It would be foolish to check the identifier without checking the entire object in most cases. We can have only one "source of truth", and therefore the recipe declares it to request.user . The group sensor (and therefore authenticated_userid ) can now depend on request.user and hope that what it returns from there has been correctly verified using the backend. Also, request.user already confirmed, and therefore speeds up subsequent calls to request.authenticated_userid .

+2
source

Martijn Pieters seems to be right.

My micro test is to verify this (in my project I use Redis as DB for users and everything else):

 print ('start test') t1 = time() authenticated_userid(self.request) print ('authenticated: ' + str(time()-t1)) t1 = time() unauthenticated_userid(self.request) print ('unauthenticated: ' + str(time()-t1)) print ('test_stop') 

Results:

 start test REDIS AUTH! # <-- actually this is query to groups finder in Redis authenticated: 0.00032901763916 unauthenticated: 7.31945037842e-05 test_stop 

It has been tested several times, the results are constant :) Do you think I should add Martijn's answer to this article in Pyramid docs to make things more “clear”? :)

+1
source

Source: https://habr.com/ru/post/1435693/


All Articles