【H5 Mui】 App 统一身份认证登录过程的记录

在 h5 app 开发的过程中,用到到统一认证登录的功能(统一身份认证登接口),来进行登录验证。
在开发 h5 app 的时候,一般会提供 app 网页版的,这时候会发现,网页版和打包的APP几乎相同,都能满足需求。

在项目中有这样一个需求:每次评论检查是否登录,否则跳转统一的登录接口,之后在进行评论。这个需求前提是自己的项目大部分浏览不需要用户登录,且对用户账号的控制并不多,这时候一般采用别的更方便的接口或API来快速搭建需要登录的模块。

  • 遇到的问题:在网页版,认证登录等操作都是基于Web的,登录成功后跳转一切正常,但是打包的 apk 却存在问题,无法跳转和跳转后如何获取到登录成功后的 code (表示登录用户的查询码,用来查询是谁,表示这个用户的唯一授权,过期需要重新登录) 。
  • CODE 的保存与使用 ,中间可能会遇到跨域传值问题。

带着上面的问题,继续看看我实际遇到的问题与解决方案。

common.js APP的所有页面都引用这个 js

// 某 统一身份认证的接口
var login_url ="http://xxx.xxxxx.cn/login?client_id=2100&redirect_uri=http://xxx.xxx.xxx.xxx/app/pages/loginto.html&response_type=code&scope=user_info&state=&toonType=100";
// 上面的地址可分为几个部分
// 一、认证接口 :http://xxx.xxxxx.cn/login
// 二、客户端ID:client_id = 2100
// 三、认证成功跳转地址:redirect_uri = http://xxx.xxx.xxx.xxx/app/pages/loginto.html
// 四、跳转后的附加参数:  &response_type=code&scope=user_info&state=&toonType=100
// 关于疑问:
// 第三项中,loginto.html 实质上是个中介页面,接受回调地址上的参数,显示“登录中正跳转”的提示
// 第四项中,包含很多关于API的控制,具体看认证接口// code 的作用 一般是用来查询用户授权的信息(表示当前用户的唯一值)
function loginToken(code){if (!code) return;// app 去查询统一身份认证平台 的接口$.ajaxJSONP('xx.xxx/xxx?code='+code,false,function(response){if (!response) return;if (response["state"] == "success") {window.token = response["token"];// localStorage 全局变量中保存,h5 的 app 每一个页面都能访问到这个值localStorage.setItem("token",window.token);}});
}    // 获取 Token
function getToken(){var token="";if(window.token){token = window.token;}else if(localStorage.getItem("token")){token = localStorage.getItem("token");}else{token =  commonjs.getOneUrlParams("token");}return token;
}// 判断是否登录
function loginIn(){var token = getToken();if(!token) {return false;}else {return true;}// 也可以继续验证 token 是否有效
}// 前往认证中心
function toAuth(){// 使用 mui 的方式 并设置不使用缓存 (打包 apk 使用缓存会出现问题)openwindow("login.html?random=" + Math.random(),{cachemode:"noCache"});
}//跳转窗口
function openwindow(_url, _styles, _extras) {if(localStorage.getItem("token")) window.token = localStorage.getItem("token");window.token && (_url = _url + (_url.indexOf("?") == -1 ? "?" : "&") + "token=" + window.token);mui.openWindow({url: _url,id: _url,styles: _styles ? _styles : {},extras: _extras ? _extras : {}, //新窗口的额外扩展参数,可用来处理页面间传值createNew: false,show: {autoShow: true},waiting: {autoShow: true,title: '正在加载...'}})
}

有了上面这样大概的认证的方法后,继续看下面 login.html 页面 和 中介 页面 loginto.html 的关系。

  • login.html 页面 在 网页版 和 apk 版 是做为登录页面的外壳而设计的,用来接收子页面的传值,子页面放在一个Iframe中。
  • loginto.html 页面 无论 网页版 还是 apk 版 都是作为回调地址 和 中介页面设计的,用来登录后接收参数,并将 code 传递给 外层(谁装载了 loginto.html 谁就是外层)
  • 上面的操作设计到跨域传值问题,解决方案:Messenger.js 只要让中介 页面 和装载他的页面 都引用这个 js 使用几个简单的方法就能将值传递过去。

Messenger.js 跨域传值的工具 js 源文件 这部分文件源码是别人写的,拿来复制,省的上传文件丢了,或不愿了解它的内部原理

/***     __  ___*    /  |/  /___   _____ _____ ___   ____   ____ _ ___   _____*   / /|_/ // _ \ / ___// ___// _ \ / __ \ / __ `// _ \ / ___/*  / /  / //  __/(__  )(__  )/  __// / / // /_/ //  __// /* /_/  /_/ \___//____//____/ \___//_/ /_/ \__, / \___//_/*                                        /____/** @description MessengerJS, a common cross-document communicate solution.* @author biqing kwok* @version 2.0* @license release under MIT license*/window.Messenger = (function(){// 消息前缀, 建议使用自己的项目名, 避免多项目之间的冲突// !注意 消息前缀应使用字符串类型var prefix = "[PROJECT_NAME]",supportPostMessage = 'postMessage' in window;// Target 类, 消息对象function Target(target, name, prefix){var errMsg = '';if(arguments.length < 2){errMsg = 'target error - target and name are both required';} else if (typeof target != 'object'){errMsg = 'target error - target itself must be window object';} else if (typeof name != 'string'){errMsg = 'target error - target name must be string type';}if(errMsg){throw new Error(errMsg);}this.target = target;this.name = name;this.prefix = prefix;}// 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀if ( supportPostMessage ){// IE8+ 以及现代浏览器支持Target.prototype.send = function(msg){this.target.postMessage(this.prefix + '|' + this.name + '__Messenger__' + msg, '*');};} else {// 兼容IE 6/7Target.prototype.send = function(msg){var targetFunc = window.navigator[this.prefix + this.name];if ( typeof targetFunc == 'function' ) {targetFunc(this.prefix + msg, window);} else {throw new Error("target callback function is not defined");}};}// 信使类// 创建Messenger实例时指定, 必须指定Messenger的名字, (可选)指定项目名, 以避免Mashup类应用中的冲突// !注意: 父子页面中projectName必须保持一致, 否则无法匹配function Messenger(messengerName, projectName){this.targets = {};this.name = messengerName;this.listenFunc = [];this.prefix = projectName || prefix;this.initListen();}// 添加一个消息对象Messenger.prototype.addTarget = function(target, name){var targetObj = new Target(target, name,  this.prefix);this.targets[name] = targetObj;};// 初始化消息监听Messenger.prototype.initListen = function(){var self = this;var generalCallback = function(msg){if(typeof msg == 'object' && msg.data){msg = msg.data;}var msgPairs = msg.split('__Messenger__');var msg = msgPairs[1];var pairs = msgPairs[0].split('|');var prefix = pairs[0];var name = pairs[1];for(var i = 0; i < self.listenFunc.length; i++){if (prefix + name === self.prefix + self.name) {self.listenFunc[i](msg);}}};if ( supportPostMessage ){if ( 'addEventListener' in document ) {window.addEventListener('message', generalCallback, false);} else if ( 'attachEvent' in document ) {window.attachEvent('onmessage', generalCallback);}} else {// 兼容IE 6/7window.navigator[this.prefix + this.name] = generalCallback;}};// 监听消息Messenger.prototype.listen = function(callback){var i = 0;var len = this.listenFunc.length;var cbIsExist = false;for (; i < len; i++) {if (this.listenFunc[i] == callback) {cbIsExist = true;break;}}if (!cbIsExist) {this.listenFunc.push(callback);}};// 注销监听Messenger.prototype.clear = function(){this.listenFunc = [];};// 广播消息Messenger.prototype.send = function(msg){var targets = this.targets,target;for(target in targets){if(targets.hasOwnProperty(target)){targets[target].send(msg);}}};return Messenger;
})();

login.html 统一身份认证登录的外壳页面

<!DOCTYPE html>
<html><head><title>登录</title></head><body><iframe id="login"  src="" ></iframe><script src="../js/mui.min.js"></script><!-- 其他JS 引用 包括 Messenger.js Common.js --><script type="text/javascript">var messenger = new Messenger('parent', 'monitor');var login = document.getElementById('login');login.src = login_url; // 转载登录页面messenger.listen(function (msg) {// 登录成功后 中介页面会调用 Messenger 的方法传值 ,这里就进行接收。loginToken(msg);    // 根据 code 获取 tokenopenwindow("home.html?random=" + Math.random(),{cachemode:"noCache"}); // 回到你想回到的地方});</sctipt></body>
</html>

loginto.html 登录的中介页面 这个是网络页面,apk 用来跳转本地页面准备的

<!DOCTYPE html>
<html><head><title>登录跳转</title></head><body><!-- 显示其他动画 --><!-- 其他JS 引用 包括 Messenger.js  --><script type="text/javascript">var messenger = new Messenger('login', 'monitor');messenger.addTarget(window.parent, "parent");if(parent!=window) {var msg = window.location.search;if(msg){msg = msg.split("code=")[1].split("&")[0];// 先外层传值messenger.targets["parent"].send(msg);} }</sctipt></body>
</html>

在进行登录时:

  • 首先会跳转到 login.html 页面,这时候 Iframe 装载的是统一身份认证的登录页,它的域不外层域内。

登录成功时:

  • Iframe 登录页 自动跳转 loginto.html ,这时的 Iframe 装载的是网络版的 中介页面而且,url 也会带有登录成功的 code 。

中介页面传值:

  • loginto.html 把 url 中的 code ,传递给外层,他的工能就完成了。

外层页面接收值:

  • code 传入后保存起来,这里外层就是你登录前的那个域内,跳转后的其它页面获取到 token 就算成功!。

注意 如果 apk 版直接跳转统一认证页面,登录成功后可能就跳转到网页版的域中,后续使用的文件全部都是 网络获取 ,而不是本地文件,这之后出现的问题都是网页版的,如果没有跳转成功,可能是 apk 的配置或者跳转方式有问题,有可能是缓存,也有可能是限制或禁止,会导致 登录后的 token 获取不到。

如有误导请联系,我会进行修正。
邮箱 hbck_gwx@qq.com

HBuilder 打包 H5 APP 进行认证登录相关推荐

  1. hbuilder php打包,关于hbuilder打包h5+app

    近日接手了一个二次开发项目,使用的是tp5框架,客户需求要做成app,这对没开发过app的我创造了一个巨大难题 作为一个php开发,对前端有一点了解,听说可以将h5直接打包成app于是我开始了我的面向 ...

  2. 解决Hbuilder打包的app返回键直接退出

    解决Hbuilder打包的app返回键直接退出 参考 https://blog.csdn.net/qq_25252769/article/details/76913083 解决打包成App后,单击 手 ...

  3. Vue项目 HBuilder X打包H5 APP

    一.准备项目 HBuilder X中:新建->项目->5+app,自定义项目名称.保存路径,选择模板"默认模板",创建.删除掉默认模板自己生成的无用的css,img,j ...

  4. vue项目利用Hbuilder打包成APP流程,以及遇到的坑

    目录 1.打包项目 1.1打包的app出现白屏. 1.2点击页面跳转不了,报 Loading chunk 2 failed. 等错误. 1.3.点手机物理按钮,直接退出程序. 2.Hbuilder发布 ...

  5. Vue HBuilder打包为app流程

    vue 打包为app 记录以下自己将web app打包成移动端app的步骤及问题 事先准备,开发完成的web app项目(也可以利用vue-cli脚手架构建vue模板项目),npm run dev可以 ...

  6. VUE项目如何使用HBuilder打包成app

    1.配置好vue.config.js 文件 在项目根目录下新建一个vue.config.js文件,并配置如下代码 module.exports = {lintOnSave: false, // 关闭格 ...

  7. 用HBuilder打包iOS App

    到官网下载HBuilder X正式版:https://www.dcloud.io/hbuilderx.html 打开HBuilder X,文件–>导入–>从本地文件导入 打开manifes ...

  8. 解决Hbuilder打包的APP微信支付时无法唤起支付,且提示{“code“:-100,“message“:“[payment微信:-1]General errors“}的问题

    依次排查: 1.menifest.json中配置了微信的appid是不是微信开放平台(微信开放平台)对应的APP id,包名是否和微信开放平台对应APP的包名一致(com.******.app) 2. ...

  9. 【uni-app】Hbuilder打包h5发行到web服务器

    开发用于在微信公众号内打开的H5, 引入了微信sdk,调用sdk的api需要将项目打包到服务器通过https才能测试,否则会报url无效 所以需要将项目部署到服务器来测试 发行前的准备工作: 打开me ...

最新文章

  1. 关于ssh国际化的记录
  2. Android在Shell环境下运行Linux命令
  3. 设计模式(二)————观察者模式
  4. python协程 无能为力_python已协程方式处理任务
  5. GUI实战|Python做一个文档图片提取软件
  6. [html] p标签里面嵌套img标签会出现向上高3像素是什么原因?如何处理?
  7. 使用双栈实现一个队列
  8. 中国内鼻扩张器市场趋势报告、技术动态创新及市场预测
  9. Gephi下载百度云加速,舒服了
  10. LiveLinkFce的Arkit与Character Creator动画曲线的对接
  11. axure文件如何加密_Axure发布到AxShare的加密与非加密方案 | 人人都是产品经理
  12. 【算法设计与分析】如何分析一个算法
  13. 二叉树非递归遍历(先序、中序、后序)(C++)
  14. 【Android】Doze模式识别与检测
  15. ATTCK实战系列——红队实战(二)
  16. 场外期权业务挂钩个股标的名单又更新啦!
  17. matlab iri模型,IRI2012电离层模型 matlab代码
  18. 生成模型-解码策略小结
  19. Windows Azure Storage 论文阅读
  20. uniapp集成colorUI uView2.0 Vuex

热门文章

  1. security面试_17道APP测试面试题分享带参考答案
  2. 听说过孤儿进程和僵尸进程嘛?
  3. 姓名评分程序PHP,php测试姓名缘分指数
  4. html 手机端的meta,H5手机端网站开发meta参数全解析
  5. 【gojs中常用的API有哪些】
  6. linuxcnc 源码解读01
  7. SQL SERVER导出模型图
  8. Windows Media Player 为什么这么弱
  9. MySQL 1251
  10. 将过滤的访问数据表导出到Excel电子表格-无截断