乐鑫Esp32学习之旅14 esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录html界面。(附带Demo)
Posted on 2019-11-04 12:00 CoreHouse 阅读(871) 评论(0) 编辑 收藏 举报- 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。
1、 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 “Hellow World”。
2、 巧用eclipes编辑器,官方教程在在Windows下搭建esp32开发环境,打印 “Hellow World”。
3、 认识基本esp32的GPIO接口,开始点亮您的第一盏 LED和中断回调实现按键功能 。
4、体会esp32的强大的定时器功能, 实现定时2s闪烁一盏LED灯。
5、接触实践esp32的pwm宽度脉冲功能, 实现呼吸效果闪烁一盏LED灯。
6、smartConfig和微信airKiss在esp32的实现,一键配网轻松快捷连接路由器。
7、利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。
8、esp32上实现本地 UDP 客户端和服务端角色,在局域网内实现通讯。
9、esp32上实现本地 TCP 客户端和服务端角色,可断线重连原路返回数据。
10、乐鑫esp32 SDK编程利用rmt驱动ws2812七彩灯,实现彩虹渐变效果。
11、入门 乐鑫esp-adf 音频框架开发,esp32造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。
12、开源一个微信公众号airkiss配网esp32以及局域网发现功能的工程,分享一个airkiss配网小工具。
13、esp32 内置 dns 服务器,无需外网访问域名返回指定网页。
14、esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录界面。
15、认识本地离线语音唤醒识别框架 esp-skainet ,实现较低成本的硬件语音本地识别控制。
16、学习本地语音唤醒离线识别框架 esp-skainet ,如何修改唤醒词? 如何自定义命令词?如何做意图动作?
17、全网首发,乐鑫esp32 sdk直连京东微联·小京鱼 · IoT开放平台,实现叮咚音响语音智能控制。
18、入门京东微联·小京鱼的控制面板H5开发,读懂vue语法,做自己的控制页面。
19、重磅开源,如何在微信小程序上ble蓝牙配网esp32,blufi的那些事!
20、一篇好文,开发过程中编译esp32固件太大,无法正常启动?教你如何自定义分区表partitions.csv。
文章目录
一、前言
最近在做esp32 wifi 配网用热点实现,已经成功实现了;效果也就是大家说的:连接esp32的热点之后,自动弹出登录输入路由器账号密码的界面;
说真的,我不想把这个博文分享出来,这个是我有道云笔记里面的一篇,因为你写的不好嘛,有人会说你讲解真费劲;发现你不是原创嘛,之后说你抄袭别人;发现你还收费卖代码?就大发雷霆地网上说你“不要脸”;卧槽,我本人还真遇到这样的事情! 之后,我在我们的qq群的 fastAdmin
开源创始人说:我们开源项目也被喷! 我突然明白,什么是网络暴力!
生活本来就难就忙,我不想理会杠精,自己写些分享博文,某些人爱看不看!
这篇是理论篇,下篇再分享输入账号密码:实现门户强制认证,连接esp32热点之后,自动强制弹出指定的html界面。
![](https://img-blog.csdnimg.cn/20191104115636572.png)
特别在此 感谢安信可科技@张工 的技术支持;
- 下面演示下效果(建议全屏观看):
- 1、不管是 iPhone 手机还是Android手机,搜索热点 “自动弹出界面” ;
- 2、连接成功之后,自动弹出一个html界面,这个html界面是自定义的;
- 3、如果苹果手机发现不会弹出,可能存在你把自动登录 取消了‘
·
二、什么是 门户强制认证
这个,我也是从网上了解到的这个名词,其中实现在 esp8266 的,传送门 ,大概总结了下:
开启热点的esp32要开启 udp 服务器和 tcp服务器,而 我上面博文也讲述了这点,有了前面的基础,我们不难发现不管是苹果手机还是Android手机,当 dns 成功之后,都会去向他们的网站去授权请求 同步网络时间等操作,如果发现返回的数据与期待的数据不对,就会认为是登录失败,会自动弹出界面;
好比我们在某些公共场所连接wifi一样,就像我上个月在旅游时候,住的一个酒店,前台给了你房间的路由器账号密码,但是你连接之后,还是不能上网的,而是需要你输入手机号码获取验证码之后才可以上网;
而连接之后,就会拦截强制弹出这样类似的登录界面;这样的例子是在太多了,记得学校的图书馆wifi也是这样,当学校宿舍的网线欠费了,就会弹出叫你付费的界面,那时候杠精,几个人公用一条网线哈哈!
![](https://img-blog.csdnimg.cn/201911041128348.png)
二、实现过程
- dns 服务器:建立无法就是一个 udp 服务器,监听 53 端口,处理数据:
static void my_dns_server(void *pvParameters)
{
uint8_t data[128];
int len = 0;
struct sockaddr_in client = { 0 };
socklen_t client_len=sizeof(struct sockaddr_in);
uint32_t i = 0;
ESP_LOGI(TAG,"DNS server start ...");
int sock = create_udp_socket(53);
if (sock < 0) {
ESP_LOGE(TAG,"Failed to create IPv4 multicast socket");
}
while(1)
{
len=recvfrom(sock,data,100,0,(struct sockaddr *)&client,&client_len); //阻塞式
if((len < 0) || ( len > 100))
{
ESP_LOGE(TAG,"recvfrom error\n");
continue;
}
printf("DNS request:");
for(i = 0x4; i< len;i++)
{
if((data[i] >= 'a' && data[i] <= 'z') || (data[i] >= 'A' && data[i] <= 'Z') ||(data[i] >= '0' && data[i] <= '9'))
printf("%c",data[i]);
else
printf("_");
}
printf("\r\n");
//printf("%d\r\n",esp_get_free_heap_size()); //打印系统可用内存
//过滤掉一些乱糟糟的域名
if( strstr((const char *)data+0xc,"taobao")||
strstr((const char *)data+0xc,"qq") ||
strstr((const char *)data+0xc,"sogou") ||
strstr((const char *)data+0xc,"amap") ||
strstr((const char *)data+0xc,"alipay")||
strstr((const char *)data+0xc,"youku") ||
strstr((const char *)data+0xc,"iqiyi") ||
strstr((const char *)data+0xc,"baidu"))
{
continue;
}
data[2] |= 0x80;
data[3] |= 0x80;
data[7] =1;
data[len++] =0xc0;
data[len++] =0x0c;
data[len++] =0x00;
data[len++] =0x01;
data[len++] =0x00;
data[len++] =0x01;
data[len++] =0x00;
data[len++] =0x00;
data[len++] =0x00;
data[len++] =0x0A;
data[len++] =0x00;
data[len++] =0x04;
data[len++] =192;
data[len++] =168;
data[len++] =4;
data[len++] =1;
/*打印客户端地址和端口号*/
// inet_ntop(AF_INET,&client.sin_addr,(char *)data,sizeof(data));
// printf("client IP is %s, port is %d\n",data,ntohs(client.sin_port));
sendto(sock,data,len,0,(struct sockaddr*)&client,client_len);
vTaskDelay(10);
}
ESP_LOGE(TAG,"DNS server stop ...");
shutdown(sock, 0);
close(sock);
vTaskDelete(NULL);
}
tcp 服务器:这个服务器,其实就是为了处理客户端的 http 请求,注意,门户强制认证不支持 https ,所以,简简单单建立一个 tcp server 返回 html 即可!
按照惯例,我们都是把一个 html 界面代码放在一个宏定义或者数组中返回,但是认真看乐鑫的demo,不难发现它是可以把 html 编译成bin文件的,也就是说,你标准写一个 html 界面就可以了;
还要特别注意,自己写html界面,要在 .mk
文件加上这么一句以表示编译:
COMPONENT_EMBED_TXTFILES := index.html
然后在引用c文件这样写:
extern const uint8_t index_html_start[] asm("_binary_index_html_start");
extern const uint8_t index_html_end[] asm("_binary_index_html_end");
//index_html_start是指针,而index_html_end - index_html_start可以得到长度
my_write(fd,index_html_start, index_html_end - index_html_start);
具体的 http header嘛,很简单,这样写:
static const char *HTTP_200 = "HTTP/1.1 200 OK\r\n"
"Server: lwIP/1.4.0\r\n"
"Content-Type: text/html\r\n"
"Connection: Keep-Alive\r\n"
"Content-Length: %d \r\n\r\n";
static const char *HTTP_400 = "HTTP/1.0 400 BadRequest\r\n"
"Content-Length: 0\r\n"
"Connection: Close\r\n"
"Server: lwIP/1.4.0\r\n\n";
三、调试心得
- 在调试过程中还发现了这几个痛点:
- 1、苹果手机和Android手机的浏览器内核不一样,导致某些情况下不会自动显示!这里我观察到,如果你的图片
base64
编码跟大,苹果手机不会显示。而Android
手机正常显示;这里我贴下:base64 图片转换地址: http://tool.oschina.net/encrypt?type=4 - 2、苹果手机连接wifi之后,wifi详情有个“自动登录”按钮,如果取消自动登录,也是无法自动弹出的,安卓的没这情况;
- 3、如果发现什么情况都不能自动弹出,那么只有访问路由器的ip地址咯!默认是
192.168.4.1
。
- 1、苹果手机和Android手机的浏览器内核不一样,导致某些情况下不会自动显示!这里我观察到,如果你的图片
本博文代码下载(不再需要积分下载,免费给大家使用)
https://github.com/xuhongv/StudyInEsp32/tree/master/13_captive_portal
另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,也欢迎留言哈!
- 玩转
esp8266
带你飞、加群付费QQ
群,不喜的朋友勿喷勿加:434878850 - esp8266源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
- esp32源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32
- 关注下面微信公众号二维码,干货多多,第一时间推送!
![](https://img-blog.csdnimg.cn/20191010143449457.png)