• 微信电脑网页二维码扫描登录简单实现


    补充:

      从后台看到,好像很多非技术人员从搜索引擎收到本博客,好像目的是因为不知道网页版的微信登录地址。这里提供一下。

      https://wx.qq.com/   点击链接,用手机微信扫描一下就可以登录了。

    正文:

      看那个微信电脑端的扫描登录看起来叼叼哒,找了一篇文章了解一下具体的实现思路和过程,看了牛人的分析后,发现实现起来也不是很难,这里我就简单的实现了一下。可能功能和流畅度没有微信做的好,具体是我对前端不是很了解。

      好了,不多说,首先要有一个二维码的生成软件才行,这里找了一个叫QrenCode的软件,好处是可以在命令行中进行生成。(下载地址: http://pkgs.org/download/qrencode 找自己合适的下载 应该还要一个依赖库libqrencode)

    1 #QrenCode 下面是centos6.4的安装命令 
    2 wget http://dl.fedoraproject.org/pub/epel/6/i386/qrencode-3.4.2-1.el6.i686.rpm
    3 wget http://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus/i586/RPMS.classic/libqrencode-3.4.3-alt1.i586.rpm 
    4 rpm -ivh libqrencode-3.4.3-alt1.i586.rpm
    5 rpm -ivh qrencode-3.4.2-1.el6.i686.rpm

      命令行生成二维码的方法

    生成二维码格式
    qrencode -o [filename.png] ‘[text/url/information to encode]‘
    参数
    -o 表示生成到指定文件
    -s num 表示生成的二维码的大小,每个点使用num个像素代替
    -v num 表示生成的版本

      创建一个login.c文件用于创建一个用于显示二维码的cgi (这里用的服务器是我博客中提到的web服务器,虽然还有bug,但是还是够用的。其他的服务器应该也是可以的。用自己的服务器会不会被骂((逃 )

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <unistd.h>
     6 #include <sys/wait.h>
     7 
     8 int rand_str(char *str,int num)
     9 {
    10     int i,j;
    11     for(i=0;i<num;i++)
    12     {
    13         j=rand()%3;
    14         if(j==0)
    15         {
    16             str[i]='a'+rand()%26;
    17         }
    18         else if(j==1)
    19         {
    20             str[i]='A'+rand()%26;
    21         }
    22         else if(j==2)
    23         {
    24             str[i]='0'+rand()%10;
    25         }
    26     }
    27     str[i]=0;
    28     return 0;
    29 }
    30 
    31 int main(int argc,char **args)
    32 {
    33     int i;
    34     char code[64];
    35     char str[64];
    36     char qc[128];
    37     char filename[64];
    38     char cmd[128];
    39     int status;
    40     pid_t pid;
    41     srand(time(NULL));
    42     rand_str(code,20);
    43 
    44 
    45     strcpy(qc,"http://192.168.198.157:8080/login/");
    46     strcat(qc,code);
    47 
    48     strcpy(filename,code);
    49     strcat(filename,".png");
    50 
    51     sprintf(cmd,"qrencode -o www/qc/%s -s 10 '%s'",filename,qc);
    52 
    53     //生成二维码
    54     system(cmd);
    55 
    56     printf("<html><head><title>扫描登录</title></head><body>");
    57     printf("<img src="%s" />",filename);
    58     printf("</body></html>");
    59 
    60     return 0;
    61 }

      运行结果,基本每次都是可以随机的。

      这里还有一点要说的,就是随机算法的问题(好像是什么十大算法之类的),我弄不了,使用的是库函数。我这个程序的随机种子是1秒一次,也就是1秒才会变换一次,还有一个问题就是这个srand函数的随机种子数好像不多,应该是6W多吧,这个如果用户一多就麻烦了。我这里想到的另一个办法是根据那个毫秒数来弄(例如用加密算法来对这个毫秒进行加密得到一个字符串,再加个什么的都可以,例如用户名什么的,最主要的是保证唯一,这个如果实际产品中实现应该不是很难)。

      接下来要做的是根据这个url地址再生成一个cgi程序,用于手机APP的调用。我这里想到的办法是每次刷新这个login页面时,就复制一个cgi程序,给APP调用。APP的调用机制是根据这个用二维码生成的url地址发送一个确认包。(确认包使用get方式可以,用post方式也可以,另外用一台服务器也是可以的,这个要看用户量等具体情况。总之就是这样了。)

      我这里为了演示的方便就采用get方式(原因嘛?我没有APP这种客户端,就简单的在手机上对这个url后面加上个参数了。)

      本次实验用到的3个程序代码 (代码中的目录问题是因为我的服务器设计有缺陷,导致有些目录要使用相对于程序的绝对路径,有的可以使用相对路径,总之我试验的时候有点坑,不过不影响代码的可读性)

      login.c

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <unistd.h>
     6 #include <sys/wait.h>
     7 
     8 int rand_str(char *str,int num)
     9 {
    10     int i,j;
    11     for(i=0;i<num;i++)
    12     {
    13         j=rand()%3;
    14         if(j==0)
    15         {
    16             str[i]='a'+rand()%26;
    17         }
    18         else if(j==1)
    19         {
    20             str[i]='A'+rand()%26;
    21         }
    22         else if(j==2)
    23         {
    24             str[i]='0'+rand()%10;
    25         }
    26     }
    27     str[i]=0;
    28     return 0;
    29 }
    30 
    31 int main(int argc,char **args)
    32 {
    33     int i;
    34     char code[64];
    35     char str[64];
    36     char qc[128];
    37     char filename[64];
    38     char cmd[128];
    39     int status;
    40     pid_t pid;
    41     srand(time(NULL));
    42     rand_str(code,20);
    43 
    44 
    45     strcpy(qc,"http://192.168.198.157:8080/qc/");
    46     strcat(qc,code);
    47 
    48     strcpy(filename,code);
    49     strcat(filename,".png");
    50 
    51     //生成二维码
    52     sprintf(cmd,"qrencode -o www/qc/%s -s 10 '%s'",filename,qc);
    53     system(cmd);
    54 
    55 
    56     printf("<html><head><title>扫描登录</title></head><body>");
    57     printf("<img src="%s" />",filename);
    58     printf("<br>如果APP上显示登录成功那么就点击该按钮进行跳转<br>");
    59     printf("<form method="get" action="welcome">");//这里的action居然不能带参数,哎前端不会啊
    60     printf("<input type="hidden" name="code" value="%s">",code);
    61     printf("<input type="submit" value="提交"></form>");
    62     printf("</body></html>");
    63 
    64     sprintf(cmd,"ln -s callback www/qc/%s",code);
    65     system(cmd);
    66 
    67     return 0;
    68 }

      callback.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int split(char **arr,char *str,const char*del)
     6 {
     7     char *s=NULL;
     8     int i=0;
     9     s=strtok(str,del);
    10     while(s!=NULL)
    11     {
    12         *arr++=s;
    13         s=strtok(NULL,del);
    14         i++;
    15     }
    16     return i;
    17 }
    18 
    19 void split_key(char *ch,char *key,char *value)
    20 {
    21     int len;
    22     int i;
    23     int j;
    24     len=strlen(ch);
    25     j=0;
    26     for(i=0;i<len;i++)
    27     {
    28         if(ch[i]=='=')
    29         {
    30             i++;
    31             break;
    32         }
    33         key[j]=ch[i];
    34         j++;
    35     }
    36     key[j]=0;
    37     j=0;
    38     for(;i<len;i++)
    39     {
    40         value[j]=ch[i];
    41         j++;
    42     }
    43     value[j]=0;
    44     return ;
    45 }
    46 
    47 int main(int argc,char **args)
    48 {
    49     char *data;
    50     char *myargs[32];
    51     int cnt=0;
    52     int i;
    53     char key[32],value[32];
    54     char username[32],code[32];
    55     char cmd[128];
    56     FILE * fp=NULL;
    57     memset(myargs,0,sizeof(myargs));
    58     memset(username,0,sizeof(username));
    59     cnt=split(myargs,args[1],"&");
    60 
    61     for(i=0;i<cnt;i++)
    62     {
    63         split_key(myargs[i],key,value);
    64         if(strcmp(key,"username")==0)
    65             strcpy(username,value);
    66         if(strcmp(key,"code")==0)
    67             strcpy(code,value);
    68     }
    69 
    70     //这里可以写上完整的网页和处理过程
    71 
    72     if(username[0]!=0)
    73     {
    74         printf("<p>通过移动端进行用户登录成功,当前登陆的用户是:</p>");
    75         printf("<font color="red">%s</font>   现在可以在浏览器中进行操作了",username);
    76     }
    77     else
    78     {
    79         printf("参数错误
    ");
    80     }
    81 
    82     sprintf(cmd,"www/qc/%s.html",code);
    83     fp=fopen(cmd,"w");
    84     fprintf(fp,"您好,用户:%s  通过APP移动端登录成功.  采用的uuid是:%s
    ",username,code);
    85     fclose(fp);
    86 
    87     return 0;
    88 }

      welcome.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 
     6 int split(char **arr,char *str,const char*del)
     7 {
     8     char *s=NULL;
     9     int i=0;
    10     s=strtok(str,del);
    11     while(s!=NULL)
    12     {
    13         *arr++=s;
    14         s=strtok(NULL,del);
    15         i++;
    16     }
    17     return i;
    18 }
    19 
    20 void split_key(char *ch,char *key,char *value)
    21 {
    22     int len;
    23     int i;
    24     int j;
    25     len=strlen(ch);
    26     j=0;
    27     for(i=0;i<len;i++)
    28     {
    29         if(ch[i]=='=')
    30         {
    31             i++;
    32             break;
    33         }
    34         key[j]=ch[i];
    35         j++;
    36     }
    37     key[j]=0;
    38     j=0;
    39     for(;i<len;i++)
    40     {
    41         value[j]=ch[i];
    42         j++;
    43     }
    44     value[j]=0;
    45     return ;
    46 }
    47 
    48 int main(int argc,char **args)
    49 {
    50     char *data;
    51     char *myargs[32];
    52     int cnt=0;
    53     int i;
    54     char key[32],value[32];
    55     char code[32];
    56     char cmd[128];
    57     memset(myargs,0,sizeof(myargs));
    58     cnt=split(myargs,args[1],"&");
    59 
    60     for(i=0;i<cnt;i++)
    61     {
    62         split_key(myargs[i],key,value);
    63         if(strcmp(key,"code")==0)
    64             strcpy(code,value);
    65     }
    66 
    67     sprintf(cmd,"www/qc/%s.html",code);
    68     //这里可以写上完整的网页
    69     if(access(cmd,F_OK)==0)
    70     {
    71         printf("终于登录了,可以各种操作了");
    72     }
    73     else
    74     {
    75         printf("请确认是否通过APP扫描登陆过");
    76     }
    77 
    78     return 0;
    79 }

      代码就放在那里,具体的操作过程就用截图方式进行讲解

      (1) 打开服务器,输入网址: http://192.168.198.157:8080/qc/login

      (2)如果没有通过移动端的的验证,此时点击提交是不起作用的。

      (3)我们使用手机客户端进行验证(由于我没有设计可用的APP,这里使用GET方式,自己构造一个。注意,如果已经有了客户端那么,可以通过客户端APP自行构造一个请求,可以是post,也可以是另外一个action然后进行验证什么的。总之怎么安全,怎么方便怎么来。)下面这个是我手机通过扫二维码,然后手动构造一个get请求得到的。(请求如下: http://192.168.198.157:8080/qc/GL199v8zsHV2bu7R7Qad?username=admin&code=GL199v8zsHV2bu7R7Qad)

      (4)好了,我们可以在那个login界面上点击登录就可以登录进去了。(这里为什么不像微信那样,APP客户端一扫描确认,浏览器就直接跳转,而是要手动点击提交按钮呢?那是因为我对前端的技术不是很了解,不知道怎么构建一个长连接,和跳转什么的。所以就弄成简单的,手动点击了,不过这些都不是重点)

      (5)下面这些是服务器的一些信息

      还有一个问题就是如果访问的次数多了,那些中间文件就太多了,这时可以通过一个脚本,按时间进行清理。

      处理的流程图

      终于完成了。心情有点小激动了。

      参考资料: http://www.linuxeden.com/html/softuse/20110328/108018.html

            http://www.zhihu.com/question/20368066 (技术原理来源)

      本文地址: http://www.cnblogs.com/wunaozai/p/3947635.html

  • 相关阅读:
    智能家居——安全信息收集(一)
    PMP软件管理之路——站在巨人的肩膀上(一)
    Linux——信息收集(二)Nikto网页服务器扫描器
    XML约束(3)
    xml基本语法(2)
    xml概述(1)
    ajax接受json响应
    ajax接受json响应(讲义)
    json与xml的比较
    零碎小技能
  • 原文地址:https://www.cnblogs.com/wunaozai/p/3947635.html
Copyright © 2020-2023  润新知