python代码启动一个Web服务器,它有这些感兴趣的网页:
import ubinascii
import utime
import socket
import select
html = """<!DOCTYPE html>
<html>
<head> <title>Ouroboros IoT Login</title> </head>
<body>
<form action="configure.html" method="POST">
Username : <input type="text" name="username"></br>
Password: <input type="password" name="password" ></br>
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>
"""
# Find out the post parameters in a dictionary
def get_post_params(req):
print("Inside POST PARAMS : req = " + req)
post_params = req.split('\r\n')[-1:][0]
# Check if the post body contains the necessary fields
# Split the post_params by &
# params : ['username=', 'password=', 'method=POST', 'url=http%3A%2F%2Ftwig-me.com%2Fv1%2Fusergroups%2FWKMUYXELA9LCC', 'jsondata=', 'submit=submit']
print("post_params : " + post_params)
params = post_params.split('&')
print("Params")
print(params)
# Initialize the key value pair dict
post_dict = {}
# Iterate on each param
for param in params:
# Each param would be like 'method=POST', etc
key_val = param.split('=')
print("Key Val :")
print(key_val)
key = key_val[0]
val = key_val[1]
# Update post_dict
post_dict[key] = val
return post_dict
# This web server takes care of the WiFi configuration
# max_run_sec
def web_server(max_run_sec = None):
# Create server socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
# TODO : If both the wifi and sta are operating simultaneously, then bind only to WiFi
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(1)
poller = select.poll()
poller.register(s, select.POLLIN)
startTimeEpoch = utime.time()
while True:
all_events = poller.poll(200) # time in milliseconds
if len(all_events) > 0:
try:
print("Just after GC Collect!")
gc.collect()
#print("Just before accepting")
res = s.accept()
client_s = res[0]
client_addr = res[1]
req = ''
req = client_s.recv(4096)
req = req.decode()
req = str(req)
# Came here means that there has been some connection!
# Reset the start time epoch in such a case:
startTimeEpoch = utime.time()
# Check route now
if req.find('configure.html') != -1:
print("Got configure request!\r\n")
# Check if the username and password are correct, if not, configure:
login_config = get_login_config()
username = login_config['user']
pwd = login_config['password']
print("Username : " + username + ", pwd : " + pwd)
# Find the POST PARAMETERS sent
# There would be just one entry in the array, so get the 0th index directly
# post_params : 'username=&password=&method=POST&url=http%3A%2F%2Fjam-me.com%2Fv1%2Fusergroups%2FWKMUYXELA9LCC&jsondata=&submit=submit'
post_dict = get_post_params(req)
# Now check if the post_dict has the key and value for username and password as needed?
username_post = post_dict['username']
password_post = post_dict['password']
# Check if the password is same as expected
if (username_post == username) and (password_post == pwd):
hidden_input = '<input type="hidden" name="username" value="' + username + '"><input type="hidden" name="passphrase" value="' + pwd + '">'
# Send the login username and password inside the hidden input field
configure_html = "<!DOCTYPE html><html><head> <title>Ouroboros IoT WiFi Configuration Page</title> </head><body><form action=\"configure_wifi.html\" method=\"POST\">WiFi SSID : <input type=\"text\" name=\"essid\"></br>WiFi Password: <input type=\"password\" name=\"passphrase\" ></br>" + hidden_input + "<input type=\"submit\" value=\"submit\" name=\"submit\"></form></body></html>"
# TODO : Also show link to webpage, where from we can change the login credentials
client_s.send(configure_html)
else:
client_s.send(login_fail_html)
elif req.find('configure_wifi.html') != -1:
# Check if the username and password are correct, if not, configure:
login_config = get_login_config()
username = login_config['user']
pwd = login_config['password']
# Get post parameters
post_dict = get_post_params(req)
# Now check if the post_dict has the key and value for username and password as needed?
username_post = post_dict['username']
password_post = post_dict['password']
# Check if the password is same as expected
if (username_post == username) and (password_post == pwd):
# Do some sanity check for handling the new wifi ssid and password
new_wifi_ssid = post_dict['essid']
new_wifi_passphrase = post_dict['passphrase']
# Set the wifi credentials
save_wifi_config(new_wifi_ssid, new_wifi_passphrase)
client_s.send('<!DOCTYPE html><html><head> <title>Ouroboros IoT WiFi Configuration Success</title> </head><body>Configuration successful!<br>Device would go into reboot now!</body></html>')
# Reboot device now
machine.reset()
else:
client_s.send(login_fail_html)
elif req.find('index.html') != -1:
print("Got index.html request!\r\n")
client_s.send(html)
else :
# Do nothing
print("Invalid request received! Show the login page again!\r\n")
client_s.send(html)
except OSError:
# Got no request and it timedout!
print("Timed-out, no request received!\r\n")
except Exception as e:
print("Got some exception\r\n")
print(str(e))
finally:
client_s.close()
if max_run_sec is not None:
elapsedTime = utime.time() - startTimeEpoch
if elapsedTime > max_run_sec:
# Max run time of web server has elapsed, time to exit this mode!
break
# Unregister poller
poller.unregister(s)
# When while loop ends!
当我访问index.html时,一切正常,网页就会出现。然而。当我在输入admin / admin而不是POST后点击提交时,我在网络服务器上收到一个GET请求,其内容如下:
Inside POST PARAMS : req = GET /configure.html HTTP/1.1
Host: 192.168.0.1
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/65.0.3325.181 Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
奇怪的是,我没有通过POST,而是获得了GET。谁能找到明显的错误?我在Ubuntu,ESP8266 micropython上使用Chromium网页浏览器。
答案 0 :(得分:1)
问题是你的HTML无效,足以让它强迫浏览器猜测我的意思模式&#34;,浏览器显然很混乱,可以猜到错误。< / p>
我无法在macOS,iOS和Android上的各种不同的Chrome,Safari和Firefox浏览器上重现问题 - 他们都正确地发送了POST
。但是,无法匹配的标签错误正是可能导致此类问题的一种方式。
特别是,您有两个</br>
标记,这些标记是您从未打开的<br>
的结束标记。很可能这只是<br />
的错字或思考(自我结束标签)。
您可能还有其他错误。在HTML5中,虽然属性名称始终不区分大小写,但并非所有属性值都是。我非常确定HTML 5.2明确要求枚举属性来进行ASCII不区分大小写的匹配,但是IIRC,HTML 5.0没有指定它。如果是这样,并且如果您的浏览器不是最新的,从技术上讲,它可以合法地将POST
视为无效值并使用无效值默认值get
,而不是将其视为post
}。我实际上并不确定这是真的 - 即使是这样,我也无法找到一个实际上就是这样的浏览器,并且无法想象任何人都有充分的理由这样做所以我怀疑这是你的问题。但仍然没有理由不做对。
因此,修复方法是将HTML更改为:
html = """<!DOCTYPE html>
<html>
<head> <title>Ouroboros IoT Login</title> </head>
<body>
<form action="configure.html" method="post">
Username : <input type="text" name="username"><br />
Password: <input type="password" name="password" ><br />
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>
"""
更一般地说,您应该始终使用外部验证器验证您的HTML,或者只使用几乎每个浏览器中内置的开发人员工具。如果您看到HTML错误或警告,请修复它们 - 特别是如果您还看到无法解释的行为,但即使您不是。