乐趣区

electron实现qq快捷登录!

之前本来想不写这个功能的, 结果客户死活要 qq 登录! 实在没办法就写了, 顺便写个文章! 在写之前有两个问题:1: 打开 qq 授权页面点击页面中的链接会又打开一个页面! …..2: 授权之后是否成功很难去判断
不过脑海中有一个想法就是,electron 就是一个类似于浏览器一样, 既然是浏览器那肯定可以阻止链接的点击 也可以判断状态! 就去啃文档了!!!
推荐大家去 w3c 去看文档 比较全 而且速度较快 文档也比较新: https://www.w3cschool.cn/elec…
https://electronjs.org/docs 这里面的响应速度比较慢 里面很多文档都很久了 参数也有失效的!!!
言归正传 说 qq 登录!
后端是使用 PHP 实现的 没什么难度, 主要的就是客户端的一些处理!
演示

放置 qq 登录按钮
<template>
<div>

<button @click=”qqLogin”>qq 登录 </button>
</div>
</template>

<script>
export default {
name: “home”,
mounted() {
this.$electron.ipcRenderer.on(‘reply’, (e, data) => {
console.log(data)
let httpCode = data.request_code[0];
if (httpCode === ‘1’) {
alert(data.token[0])
}
})
},
methods: {
qqLogin() {
// 请求服务器获取授权页面和参数
this.$http.get(‘xxxxx’)
.then((result) => {
if (result.data.status === 1) {
this.$electron.ipcRenderer.send(‘qqLogin’, {url: result.data.data});
}
})
.catch()
},
}
}
</script>
问题解决
点击 a 链接会打开一个新窗口
解决打开 qq 授权页面点击页面中的链接会又打开一个窗口的问题 使用 webContents 的 new-window 事件 组织默认事件 调用 Shell 利用默认浏览器打开就行了!
loginWindow.webContents.on(‘new-window’, (event, url) => {
event.preventDefault();
shell.openExternal(url);
});
授权后是否成功很难去判断
到这个问题后我就想到一个词 那就是 Response 和 code 然后就去搜索了嘛 结果在 webContents 找到了! did-get-redirect-request 事件 ! 但是我们不能直接使用他 要在点击授权之后再去使用他
loginWindow.webContents.on(‘will-navigate’, (e, url,) => {
content.on(‘did-get-response-details’, (e, status, url, originalURL, httpResponseCode, requestMethod, referrer, header) => {
if (httpResponseCode === 200) {
event.sender.send(‘reply’, header);
// loginWindow.close();
}
})
});
will-navigate 事件解释: 当用户或 page 想要开始导航的时候发出事件. 它可在当 window.location 对象改变或用户点击 page 中的链接的时候发生. 当使用 api(如 webContents.loadURL 和 webContents.back) 以编程方式来启动导航的时候,这个事件将不会发出. 它也不会在页内跳转发生,例如点击锚链接或更新 window.location.hash. 使用 did-navigate-in-page 事件可以达到目的
did-get-response-details 事件解释: 当有关请求资源的详细信息可用的时候发出事件. status 标识了 socket 链接来下载资源.
拿到这两个之后我们就可以写代码啦! 在点击授权之后授权页面会跳转到我们服务器的一个回调地址 在里面做一个操作 比如获取用户 token 乱七八糟的! 之后将生成的 token 返回给客户端!
但是要注意这里服务端返回的数据客户端不能解析 大家可以使用:findInPage 去查询返回的内容! 但是我没去这么做
因为 did-get-response-details 事件返回了:status,newURL,originalURL,httpResponseCode,requestMethod,referrer,headers 八个参数 最后我们只需要判断 httpResponseCode 是 200 的时候 将 header 里面的参数从主进程返回给渲染进程大概的数据是这样的:
access-control-allow-credentials:[“true”]
access-control-allow-headers:[“token,Origin, X-Requested-With, Content-Type, Accept”]
access-control-allow-methods:[“POST,GET,DELETE,PUT”]
cache-control:[“no-store, no-cache, must-revalidate”]
connection:[“Keep-Alive”]
content-type:[“application/json; charset=utf-8”]
date:[“Sun, 21 Oct 2018 14:02:20 GMT”]
expires:[“Thu, 19 Nov 1981 08:52:00 GMT”]
keep-alive:[“timeout=5, max=100”]
request_code:[“1”]
msg:[“ 登录成功 ”]
token:[“xxxxxxxx”]
pragma:[“no-cache”]
server:[“Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9”]
set-cookie:[“PHPSESSID=6b0esq5jd8vloess2c96ove86s; path=/; HttpOnly”]
transfer-encoding:[“chunked”]
x-powered-by:[“PHP/7.2.1”]
以上参数中 msg request_code token 为自定义参数 是服务器代码生成的!
能得到这些就好办了!
渲染进程拿到 header 中的 token 根据 token 获取用户信息这之后就简单的很了!!!
主进程代码:
import {ipcMain, BrowserWindow, shell} from ‘electron’

ipcMain.on(‘qqLogin’, (event, data) => {
const loginWindow = new BrowserWindow({
width: 750,
height: 450,
resizable: false,
minimizable: false,
maximizable: false,
webPreferences: {
devTools: false,
}
});

loginWindow.setMenu(null);

loginWindow.loadURL(data.url);

loginWindow.webContents.on(‘new-window’, (event, url) => {
event.preventDefault();
shell.openExternal(url);
});
const content = loginWindow.webContents;

content.on(‘will-navigate’, (e, status, url,) => {
content.on(‘did-get-response-details’, (e, status, url, originalURL, httpResponseCode, requestMethod, referrer, header) => {
if (httpResponseCode === 200) {
event.sender.send(‘reply’, header);
loginWindow.close();
}
})
});
});
注意点
返回的 header 里面是一个数组 这种写法真是坑爹啊! 还要去写一个 header.token[0] 这种写法有点不喜欢 但是没法子!

退出移动版