背景
项目基于angular1.3开发
web服务器用node,提供微信授权和跨域
使用微信jssdk获取经纬度,再利用百度地图API获取用户所在城市
待优化问题:
项目的微信授权基于老的项目,写的有点不够优雅;
自己开发时把授权信息存到了sessionStorage里面,导致每次进入项目都要走一遍授权,浪费时间和影响用户体验;
解决方案:
重写授权,让项目初始化时只请求一个接口,就可以拿到用户的基本信息;将获取的用户基本信息存在cookie里面,并设置一个比较长的过期时间,以便用户在某一段时间内访问可以不用再次授权,拿微信授权的相关代码就贴在下面了.
服务端用node+express
路由部分
router.js
/**
* router
*/
const express = require("express");
const router = express.Router();
const wxAuth = require("../wxAuth.js");
router.get("/auth", wxAuth.getCode, (req, res, next) => {
// 授权调用
});
router.get("/wxAuth/getUserInfo", wxAuth.getAccessToken, wxAuth.getUserInfo, (req, res, next) => {
let back_url = req.query.back_url;
console.log('back_url=='+back_url);
if (back_url.indexOf('?path=')) {
back_url = back_url.replace('?path=','#/')
console.log(back_url);
}
res.redirect(back_url);
});
module.exports = router;
授权中间件 wxAuth.js
//微信公众号的appId和appSecret配置文件
const weixin = require("../weixin.config.js")
const request = require('request')
const appId = weixin.appID;
const appSecret = weixin.appsecret;
const Host = 'http://example.com'
exports.getCode = (req, res, next) => {
if (req.cookies && req.cookies.openid) {
next();
} else {
console.log(req)
let back_url = escape(req.query.back_url);
console.log(req.query.back_url)
let redirect_url = `http://mall.yizhenjia.com/wxAuth/getUserInfo?back_url=${back_url}`;
let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_url}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect `;
console.log(url);
res.redirect(url);
}
}
exports.getAccessToken = (req, res, next) => {
console.log('====accessToken')
// console.log(req.query)
let code = req.query.code;
let url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${appSecret}&code=${code}&grant_type=authorization_code `;
request(url, (error, response, body) => {
let result = JSON.parse(body);
console.log(result)
req.access_token = result.access_token;
req.openid = result.openid;
next();
});
}
exports.getUserInfo = (req, res, next) => {
console.log('====getUserInfo')
let access_token = req.access_token;
let openid = req.openid;
let url = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}&lang=zh_CN `
request(url, (error, response, body) => {
console.log(body)
let result = JSON.parse(body);
res.cookie("openid", result.openid, { maxAge: 24 * 60 * 60 * 1000, httpOnly: false });
res.cookie("unionid", result.unionid, { maxAge: 24 * 60 * 60 * 1000, httpOnly: false });
res.cookie("nickname", result.nickname, { maxAge: 24 * 60 * 60 * 1000, httpOnly: false });
res.cookie("headimgurl", result.headimgurl, { maxAge: 24 * 60 * 60 * 1000, httpOnly: false });
next();
});
}
在angular项目启动的时候,就判断有没有用户union的cookie存在,如果不存在就去授权,并阻止视图渲染
获取授权,因为微信授权的时候,会忽略angular路由的哈希值后面的内容,所以把哈希值做了转换,在服务端的router.js里面,又把哈希值还原,在重定向的时候写在url里
//放在commonUtil服务里面
转换url,将路由参数传给服务器,然后在授权结束后,在重定向的url里获取路由的哈希值(这里的哈希处理更多的是为了后面微信支付路径的问题)
self.getAuth = function() {
var hash = window.location.hash.replace('#/', '?path=');
var origin = window.location.origin;
var pathname = window.location.pathname;
var bcakUrl = origin + pathname + hash;
window.location.href = "/auth?back_url=" + bcakUrl;
}
判断授权,没有授权情况下阻止默认渲染,并请求授权(在其他框架的时候也可以做类似处理)
$rootScope.$on('$stateChangeStart', function(event) {
if (!cookieUtil.hasCookie("unionid") || !cookieUtil.hasCookie("openid")) {
commonUtil.getAuth();
event.preventDefault();
}
});
//cookieUtil判断cookie是否存在,设置cookie和获取cookie值(angular service)