乐鑫Esp32学习之旅14 esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录html界面。(附带Demo)


  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

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界面。


     特别在此 感谢安信可科技@张工 的技术支持;


  • 下面演示下效果(建议全屏观看):
    • 1、不管是 iPhone 手机还是Android手机,搜索热点 “自动弹出界面” ;
    • 2、连接成功之后,自动弹出一个html界面,这个html界面是自定义的;
    • 3、如果苹果手机发现不会弹出,可能存在你把自动登录 取消了‘

·


二、什么是 门户强制认证


     这个,我也是从网上了解到的这个名词,其中实现在 esp8266 的,传送门 ,大概总结了下:

     开启热点的esp32要开启 udp 服务器和 tcp服务器,而 我上面博文也讲述了这点,有了前面的基础,我们不难发现不管是苹果手机还是Android手机,当 dns 成功之后,都会去向他们的网站去授权请求 同步网络时间等操作,如果发现返回的数据与期待的数据不对,就会认为是登录失败,会自动弹出界面;

     好比我们在某些公共场所连接wifi一样,就像我上个月在旅游时候,住的一个酒店,前台给了你房间的路由器账号密码,但是你连接之后,还是不能上网的,而是需要你输入手机号码获取验证码之后才可以上网;

     而连接之后,就会拦截强制弹出这样类似的登录界面;这样的例子是在太多了,记得学校的图书馆wifi也是这样,当学校宿舍的网线欠费了,就会弹出叫你付费的界面,那时候杠精,几个人公用一条网线哈哈!


二、实现过程


  • 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
本博文代码下载(不再需要积分下载,免费给大家使用)

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
  • 关注下面微信公众号二维码,干货多多,第一时间推送!
发布了152 篇原创文章 · 获赞 785 · 访问量 79万+

猜你喜欢

转载自blog.csdn.net/xh870189248/article/details/102892766