首先本次开发用到了vue作为本次前端开发框架,weui作为前端UI框架。设计思路无论用户进入哪个页面,都要进行身份的认证。具体的身份认证流程如下图所示。
需要注意的坑
- 坑1:在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头
解决:本地测试需要用到外网穿透。我们用的花生壳将本地访问找一个类似于域名代理地址室的东西。将微信公众号js域名认证的txt文件下载放在跑起来的项目当中,进行域名认证(我尝试放在vue项目中的和index.html同层级中但是访问不到,放在static中可以即域名认证里填写的也是“域名/static”。但是不是根目录,访问路由地址“域名/#/home”就访问不到),于是在本地跑了一个Tomcat,再将txt文件放在根目录下,运行即可。
具体操作如下:
找到tomcat的下载地址对应的根目录下,如果webapps下没有ROOT文件夹一定要新建一个ROOT文件夹,不然还是访问不到。然后将txt文件放在ROOT下,运行tomcat.
双击bin/startup.sh运行tomcat。
2. 坑二网页授权的两种scope的区别说明
开始做测试的时候以为其实scope的区别不明显,但是为了防止出现错误用了scope=snsapi_userinfo,但是后来还是忍不住将代码改成了scope=snsapi_base,好奇心害死猫,手欠害死自己,当时也没在意,后来后端接口总给我返回报错。原来是我给后端用scope=snsapi_base拿到的的code后端拿不到用户基本信息。
- **坑三:**因为我们无法控制用户是从哪个页面进入,但是每个页面都需需要进行身份的验证,每个页面都要从localstorage拿数据吗?
在App.vue中解决这些吧,在App.vue中定义一个globalUserInfoData,页面需要的数据都从这里去取。每个页面监听globalUserInfoData的变化来更新页面数据:
页面之间逻辑如下图所示:
//**----------------------------------APP.vue----------------------------------------**
<template>
<div id="app">
<router-view :globalData="globalUserInfo" @loginAPI="loginFun" @setGlobalUserAPI="setGlobalUserInfo"/>
</div>
</template>
<script type="text/ecmascript-6">
import { getIsRegist, login,ajaxSubmit ,_localBaseUrl,_AppID} from "@/api/http";
export default {
name: 'App',
data(){
return{
globalUserInfo:null
}
},
created:function(){
var localData=localStorage.getItem("userInfo");
if(localData){
this.globalUserInfo=JSON.parse(localData)
}
if(!this.globalUserInfo){
var _code = this.getQueryString("code");
if (_code) {//获取code回调地址,通过code获取用户基本信息
ajaxSubmit(
this.$http,
getIsRegist,
"get",
{ code:_code },
resData => {
if(resData.result==0){
if(resData.data.isRegist){//注册过
this.loginFun(resData.data.userId)
}else{//未注册
var globalData={}
globalData.isRegist=resData.data.isRegist
var baseInfo={}
baseInfo.openid=resData.data.userInfo.openid
baseInfo.nickname=resData.data.userInfo.nickname
baseInfo.avatarUrl=resData.data.userInfo.headimgurl
globalData.userInfo={...baseInfo}
globalData.isPayFlag=false
this.globalUserInfo={...globalData}
}
}else{
//未注册的用户刷新页面。地址上被拼接上了code导致code过期,刷新地址栏
window.location.href=_localBaseUrl
}
}
);
}else{
//没有微信用户信息,没有授权-->> 需要授权,跳转授权页面
var _redirectUrl=encodeURIComponent(_localBaseUrl+"login")
var getUserInfoUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+_AppID+"&redirect_uri="+_redirectUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
window.location.href=getUserInfoUrl
}
}
},
mounted:function(){
},
methods:{
getQueryString(name) {
if(window.location.href.search(name + "=") != -1 ){
var nameValue=window.location.href.split(name + "=")[1].split("&")[0];
return nameValue;
}else{
return null;
}
},
loginFun(_userId){
var globalData={}
globalData.userId=_userId
//登陆
ajaxSubmit(
this.$http,
login,
"post",
{ userId:_userId},
resData => {
globalData.isRegist=true
globalData.isPayFlag=resData.data.isPayFlag
globalData.userInfo=resData.data.user
this.globalUserInfo={...globalData}
//存储到localstorage
localStorage.setItem("userInfo",JSON.stringify(this.globalUserInfo))
}
)
},
//修改全局变量给globalUserInfo
setGlobalUserInfo(){
var localData=localStorage.getItem("userInfo");
if(localData){
this.globalUserInfo=JSON.parse(localData)
}
}
}
}
</script>
//----------------------------------login.vue----------------------------------------
<template>
<div class="login">
<div class="tempImg">
<img src="../../../static/image/timg (2).gif" style="display: block;width: 100%;">
<p>正在登录...</p>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import {
ajaxSubmit,
} from "@/api/http";
export default {
name: 'login',
props:{
globalData:{
type: Object
}
},
created:function(){
},
watch: {
globalData:{
immediate: true, // 这句重要
handler (val) {
if(val){
var that=this
setTimeout(function(){
that.$router.push("/")
},500)
}
}
}
},
}
</script>
在子页面监听globalUserInfo的变化,这样可以及时的监听到globalUserInfo的变化,更改页面
watch: {
globalData: {
immediate: true,//很重要
handler(val) {
if (val) {
this.isRegist = val.isRegist;
}
}
}
},
如果调用其他接口时出现session失效的问题,调用父组件的loginFun方法。进行从新登陆。
未解决的问题
- 导航栏,导航栏是每个页面都需要的,所以想加在app.vue中,但是在app.vue中没办法获取到this.router。怎么判断给哪个导航栏加高亮?每次都拿地址吗?地址变化太多了。可能被拼接上code,有的带参数。从地址栏直接拿太麻烦了吧?
- 地址栏被拼接上了code,如何解决?