patternpythonMinor
Basic web app that returns a JSON of information
Viewed 0 times
appthatreturnswebjsonbasicinformation
Problem
My web application can take URL-encoded strings and return a JSON that contains information, like API calls.
My main concerns are with security. I need a cheap and easy (but secure) way to do certain commands. This part is handled by the
at line 12 to:
should be fine, allowing you to access this server from
My server is currently operational at here.
```
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import ssl, reactor
from twisted.python.modules import getModule
import urllib.parse
import cgi
import json
import os
import hashlib
admin_salt = ''
realpass = ''
port = int(os.environ.get('PORT', 17995))
class FormPage(Resource):
isLeaf = True
def render_GET(self, request):
out = {}
print(request.uri)
x = (request.uri).decode('ascii')
x = x[1:]
x = todi(x)
request.setHeader('Content-Type', 'text/plain; charset=UTF-8')
valid = False
if 'adminaccess' in x:
vlr = adminhandle(x)
out.update({'ADMIN':vlr[0]})
if len(vlr) != 1:
out.update({'CMDRES':vlr[1]})
if 'key' in x:
if x['key'] == 'chess':
valid = True
out.update({'my_name':'Bob'})
out.update({'success':valid})
return json.dumps(out).encode('UTF-8')
## def render_POST(self, request):
## x = request.content.read()
## print(x)
## return x
def todi(st):
if len(st) == 0:
return '{}'
if st[len(st)-1] == '/':
st = st[:-1]
My main concerns are with security. I need a cheap and easy (but secure) way to do certain commands. This part is handled by the
adminhandle section of the code. My code is currently designed to be able to be deployed on a heroku app, but simply changing:port = int(os.environ.get('PORT', 17995))at line 12 to:
port = 80should be fine, allowing you to access this server from
http://localhost. Inside the code itself contains a hashed password and a salt. The password I use I generated with the random module (perhaps it is worth noting, since there are "more secure" RNGs out there).My server is currently operational at here.
```
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import ssl, reactor
from twisted.python.modules import getModule
import urllib.parse
import cgi
import json
import os
import hashlib
admin_salt = ''
realpass = ''
port = int(os.environ.get('PORT', 17995))
class FormPage(Resource):
isLeaf = True
def render_GET(self, request):
out = {}
print(request.uri)
x = (request.uri).decode('ascii')
x = x[1:]
x = todi(x)
request.setHeader('Content-Type', 'text/plain; charset=UTF-8')
valid = False
if 'adminaccess' in x:
vlr = adminhandle(x)
out.update({'ADMIN':vlr[0]})
if len(vlr) != 1:
out.update({'CMDRES':vlr[1]})
if 'key' in x:
if x['key'] == 'chess':
valid = True
out.update({'my_name':'Bob'})
out.update({'success':valid})
return json.dumps(out).encode('UTF-8')
## def render_POST(self, request):
## x = request.content.read()
## print(x)
## return x
def todi(st):
if len(st) == 0:
return '{}'
if st[len(st)-1] == '/':
st = st[:-1]
Solution
The first problem is the function
This strips of any
Your function
Your placeholder variable
todi. I'm assuming a better name for it would be to_dict. If that is the case it does not make sense, that it sometimes returns the string "{}", sometimes "()" and sometimes an actual dictionary. I think this would be equivalent/better:def to_dict(st):
st = st.strip("/?")
if not st:
return dict()
return dict(urllib.parse.parse_qsl(st))This strips of any
"/" or "?" from the beginning or end of the string and returns an empty dictionary if the string is empty.Your function
adminhandle should take the parameters it needs as parameters, not retrieve them on its own from data. It can also be slightly simplified by using the fact that lists are mutable, so you can just write result[0] = True instead of del result[0]; result.append(True):def adminhandle(adminaccess, command):
result = [False, ""]
if adminaccess is not None:
rawupass = (admin_salt+adminaccess).encode('ascii')
hashupass = hashlib.sha512(rawupass).hexdigest()
if hashupass == realpass:
#access granted!
result[0] = True
if command == 'listdir':
result[1] = str(os.listdir(os.getcwd()))
return resultx is also a really bad name. At least name it data or something telling the reader what it actually is.data = to_dict(request.uri.decode('ascii')[1:])Your placeholder variable
valid is also not necessary. As is writing out.update({'success': valid}). out['success'] = valid is sufficient. I would also use the fact that dictionaries have a dict.get method, that returns None if the key does not exist.out = {'success': False}
adminaccess, command = data.get('adminaccess'), data.get('command')
out['ADMIN'], out['CMDRES'] = adminhandle(adminaccess, command)
if not out['CMDRES']:
del out['CMDRES']
if data.get('key') == 'chess':
out['my_name'] = 'Bob'
out['success'] = True
return json.dumps(out).encode('UTF-8')Code Snippets
def to_dict(st):
st = st.strip("/?")
if not st:
return dict()
return dict(urllib.parse.parse_qsl(st))def adminhandle(adminaccess, command):
result = [False, ""]
if adminaccess is not None:
rawupass = (admin_salt+adminaccess).encode('ascii')
hashupass = hashlib.sha512(rawupass).hexdigest()
if hashupass == realpass:
#access granted!
result[0] = True
if command == 'listdir':
result[1] = str(os.listdir(os.getcwd()))
return resultdata = to_dict(request.uri.decode('ascii')[1:])out = {'success': False}
adminaccess, command = data.get('adminaccess'), data.get('command')
out['ADMIN'], out['CMDRES'] = adminhandle(adminaccess, command)
if not out['CMDRES']:
del out['CMDRES']
if data.get('key') == 'chess':
out['my_name'] = 'Bob'
out['success'] = True
return json.dumps(out).encode('UTF-8')Context
StackExchange Code Review Q#148322, answer score: 2
Revisions (0)
No revisions yet.