Let SessionManager.get require Request object; Check IP addr.
So far there is no use case in which get needs to be called with something other than a Request, and I don't think there will be. So let's make that part of the design and we can also take the opportunity to check IP.
This commit is contained in:
		
							parent
							
								
									c6a396c658
								
							
						
					
					
						commit
						6f4530c88c
					
				
					 1 changed files with 18 additions and 6 deletions
				
			
		|  | @ -7,6 +7,7 @@ import werkzeug.wrappers | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| SESSION_MAX_AGE = 86400 | SESSION_MAX_AGE = 86400 | ||||||
|  | REQUEST_TYPES = (flask.Request, werkzeug.wrappers.Request, werkzeug.local.LocalProxy) | ||||||
| 
 | 
 | ||||||
| def _generate_token(length=32): | def _generate_token(length=32): | ||||||
|     randbytes = os.urandom(math.ceil(length / 2)) |     randbytes = os.urandom(math.ceil(length / 2)) | ||||||
|  | @ -15,10 +16,13 @@ def _generate_token(length=32): | ||||||
|     return token |     return token | ||||||
| 
 | 
 | ||||||
| def _normalize_token(token): | def _normalize_token(token): | ||||||
|     if isinstance(token, (flask.Request, werkzeug.wrappers.Request, werkzeug.local.LocalProxy)): |     if isinstance(token, REQUEST_TYPES): | ||||||
|         request = token |         request = token | ||||||
|         token = request.cookies.get('etiquette_session', None) |         token = request.cookies.get('etiquette_session', None) | ||||||
|         if token is None: |         if token is None: | ||||||
|  |             # During normal usage, this does not occur because give_token is | ||||||
|  |             # applied *before* the request handler even sees the request. | ||||||
|  |             # Just a precaution. | ||||||
|             message = 'Cannot normalize token for request with no etiquette_session header.' |             message = 'Cannot normalize token for request with no etiquette_session header.' | ||||||
|             raise TypeError(message, request) |             raise TypeError(message, request) | ||||||
|     elif isinstance(token, str): |     elif isinstance(token, str): | ||||||
|  | @ -35,10 +39,15 @@ class SessionManager: | ||||||
|     def add(self, session): |     def add(self, session): | ||||||
|         self.sessions[session.token] = session |         self.sessions[session.token] = session | ||||||
| 
 | 
 | ||||||
|     def get(self, token): |     def get(self, request): | ||||||
|         token = _normalize_token(token) |         token = _normalize_token(request) | ||||||
|         session = self.sessions[token] |         session = self.sessions[token] | ||||||
|         if session.expired(): |         invalid = ( | ||||||
|  |             request.remote_addr != session.ip_address or | ||||||
|  |             session.expired() | ||||||
|  |         ) | ||||||
|  |         if invalid: | ||||||
|  |             self.remove(token) | ||||||
|             raise KeyError(token) |             raise KeyError(token) | ||||||
|         return session |         return session | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +68,7 @@ class SessionManager: | ||||||
|                 request.cookies['etiquette_session'] = token |                 request.cookies['etiquette_session'] = token | ||||||
| 
 | 
 | ||||||
|             try: |             try: | ||||||
|                 session = self.get(token) |                 session = self.get(request) | ||||||
|             except KeyError: |             except KeyError: | ||||||
|                 session = Session(request, user=None) |                 session = Session(request, user=None) | ||||||
|                 self.add(session) |                 self.add(session) | ||||||
|  | @ -85,8 +94,11 @@ class SessionManager: | ||||||
| 
 | 
 | ||||||
|     def remove(self, token): |     def remove(self, token): | ||||||
|         token = _normalize_token(token) |         token = _normalize_token(token) | ||||||
|         if token in self.sessions: |         try: | ||||||
|             self.sessions.pop(token) |             self.sessions.pop(token) | ||||||
|  |         except KeyError: | ||||||
|  |             pass | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class Session: | class Session: | ||||||
|     def __init__(self, request, user): |     def __init__(self, request, user): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue