基于uniapp与node.js实现的微信授权登录功能实例

 更新时间:2023年05月25日 10:57:54   作者:@李优秀  
前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术,下面这篇文章主要给大家介绍了关于如何基于uniapp与node.js实现的微信授权登录功能的相关资料,需要的朋友可以参考下

前言

小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

注意事项

  • 会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
  • 临时登录凭证 code 只能使用一次

授权

部分接口需要经过用户授权同意才能调用。我们把这些接口按使用范围分成多个 scope ,用户选择对 scope 来进行授权,当授权给一个 scope 之后,其对应的所有接口都可以直接使用。此类接口调用时:

  • 如果用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意后方可调用接口;
  • 如果用户已授权,可以直接调用接口;
  • 如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调。请开发者兼容用户拒绝授权的场景。

express脚手架配置

第一步:在node.js安装完成的情况下搭建express脚手架,并在在根目录新建config.js,内容如下:

// token全局配置文件
module.exports = {
    // 加密和解密的token秘钥(引号中的字符可以自定义)
    jwtSecretKey: 'advance8',
    // token有效期
    expiresIn: '8640h'
}

第二步:在routes下新建router_handle/wxuser.js,并引入数据库连接模块以及config.js,内容如下:

const request = require('request')
//引入连接数据库模块
const db = require('../conn')
//连接数据
db.connect(() => {
    console.log("连接成功")
})
const jwt = require("jsonwebtoken");// 导入生成token的包
const config = require("../../config");
const { jwtSecretKey } = require("../../config");
exports.wxuser = (req, res) => {
    let params = req.body; // 接收小程序端传过来的所有数据
    let code = params.code; //获取小程序传来的code
    let encryptedData = params.encryptedData; //获取小程序传来的encryptedData
    let iv = params.iv; //获取小程序传来的iv
    let userInfo = JSON.parse(params.userInfo); //获取个人信息
    let appid = ""; //自己小程序后台管理的appid,可登录小程序后台查看
    let mysecret = ""; //小程序后台管理的secret,可登录小程序后台查看
    let grant_type = "authorization_code"; // 授权(必填)默认值
    //请求获取openid
    let url =
        "https://api.weixin.qq.com/sns/jscode2session?grant_type=" +
        grant_type +
        "&appid=" +
        appid +
        "&mysecret=" +
        mysecret +
        "&js_code=" +
        code;
    request(url, (err, response, body) => {
        if (!err && response.statusCode == 200) {
            // 服务器返回的openid、sessionKey
            let _data = JSON.parse(body);
            _data.code = code;
            _data.session_key = "";
            // 对用户信息进行加密生成字符串
            const wxToken = jwt.sign(_data, jwtSecretKey, {
                expiresIn: config.expiresIn,
            });
            // 定义sql 语句,查询当前用户是否存在(openid)
            const sql = `select * from WeChatUser where user_id = ?`;
            db.query(sql, _data.openid, (err, result) => {
                if (err) return res.cc(err); //res.cc为自定义封装,可以换成res.send
                if (result.length === 0) {
                    const sql = `insert into WeChatUser  set ?`;
                    db.query(
                        sql, {
                            user_id: _data.openid,
                            nickName: userInfo.nickName,
                            avatar: userInfo.avatarUrl,
                            gender: userInfo.gender,
                        },
                        (err, result) => {
                           if (err) return res.cc(err);
                           if (result.affectedRows !== 1) return res.cc("授权失败,请重试");
                           res.send({
                                token: "Bearer " + wxToken,
                                status: 200,
                                messages: "WX授权成功",
                            });
                        }
                    );
                } else {
                    const sql = `update WeChatUser set ? where user_id = ?`;
                    db.query(
                        sql, [{
                                user_id: _data.openid,
                                nickName: userInfo.nickName,
                                avatar: userInfo.avatarUrl,
                                gender: userInfo.gender,
                            },
                            _data.openid,
                        ],
                        (err, result) => {
                            if (err) return res.cc(err);
                            res.send({
                                token: "Bearer " + wxToken,
                                status: 200,
                                messages: "WX授权成功",
                            });
                        }
                    );
                }
            });
        } else {
            res.cc("请求openid失败");
        }
    });
};

第三步:分别是路由模块以及app.js的配置

var express = require('express');
var router = express.Router();
 
//引入连接数据库模块
const conn = require('./conn')
 
//连接数据
conn.connect(() => {
    console.log("WeChatUser表连接成功")
})
var jsonWrite = function(res, ret) {
    if (typeof ret === 'undefined') {
        res.json({
            code: '1',
            msg: '操作失败'
        });
    } else {
        res.json(
            ret
        );
    }
};
/*获取微信用户列表*/
router.post('/wxuserList', (req, res) => {
    const sqlStr = `select * from WeChatUser`
    conn.query(sqlStr, function(err, result) {
        if (err) {
            console.log(err);
        }
        if (result) {
            jsonWrite(res, result);
        }
    })
});
 
const wxuserHandle = require('./router_handle/wxuser')
router.post('/wxuser', wxuserHandle.wxuser)
 
module.exports = router;
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
 
var app = express();
 
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
 
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'code/public')));
// error handler
app.use(function(err, req, res, next) {
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};
    res.status(err.status || 500);
    res.render('error');
});
 
const wxuserApi = require('./routes/index');
// 允许跨域
app.all('*', function(req, res, next) {
    console.log(req.headers.origin)
    console.log(req.environ)
        // res.header("Access-Control-Allow-Origin", req.headers.origin);
        //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type");
    //跨域允许的请求方式 
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    if (req.method == 'OPTIONS') {
        /*让options请求快速返回*/
        res.sendStatus(200)
    } else {
        next()
    }
});
 
app.use('/wxuser', wxuserApi);
 
//配置默认端口
app.listen(3008, () => {
    console.log("服务器已启动")
})
module.exports = app;

最后,启动服务器,显示如下内容表示成功

uniapp配置

HTML

<button class="cu-btn block bg-green margin-tb-sm lg shadow" @click="getUserProfile"> 
        微信一键登录
</button>

JS

methods(){
getUserProfile: function(e) {
		var that=this;
				// 获取个人信息
		wx.getUserProfile({
		desc: '用于获取用户个人信息',
		success: function(detail) {
				wx.login({
					success(res) {
					var code = res.code; //登录凭证
						uni.request({
							url: '', 
							// 需要传给后端的数据
							data: {
								encryptedData: detail.encryptedData,
								iv: detail.iv,
								code: code,
								userInfo: detail.rawData
							},
								method: 'post',
								success: function(res) {
									// 将用户授权信息存储到本地
								wx.setStorageSync('userinfo', detail.userInfo)
								// 将后端返回的token存储到本地
								wx.setStorageSync('token', res.data.token)
                                //通过接口获取数据库中数据
								uni.request({
								    url:'',
									data: {},
									method: 'post',
									header: {
										'content-type': 'application/json'
										},
									success: (res) => {
									   that.nickName=res.data[0].nickName
									   that.avatar=res.data[0].avatar
											}
										})
									},
									fail: function() {
										console.log('系统错误')
									}
								})
							}
						});
					},
					fail: function() {
						wx.showModal({
							content: '取消授权将会影响相关服务,您确定取消授权吗?',
							success(res) {
								if (res.confirm) {
									wx.showToast({
										title: '已取消授权',
										duration: 1500
									})
								} else if (res.cancel) {
									this.getUserProfile()
								}
							}
						})
					}
				})
			}
        }

运行结果

总结

到此这篇关于基于uniapp与node.js实现的微信授权登录功能的文章就介绍到这了,更多相关uniapp与node.js微信授权登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • pnpm workspace管理monorepo项目使用过程详解

    pnpm workspace管理monorepo项目使用过程详解

    这篇文章主要为大家介绍了pnpm workspace管理monorepo项目使用过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • nodejs之请求路由概述

    nodejs之请求路由概述

    这篇文章主要介绍了nodejs的请求路由概述,需要的朋友可以参考下
    2014-07-07
  • Node.js开发之套接字(socket)编程入门示例

    Node.js开发之套接字(socket)编程入门示例

    这篇文章主要介绍了Node.js开发之套接字(socket)编程,结合简单实例形式分析了node.js套接字socket客户端与服务器端相关实现与使用技巧,需要的朋友可以参考下
    2019-11-11
  • node.js域名解析实现方法详解

    node.js域名解析实现方法详解

    这篇文章主要介绍了node.js域名解析实现方法,结合实例形式详细分析了node.js使用dns.lookup()及dns.resolve4()进行域名解析的相关操作技巧与注意事项,需要的朋友可以参考下
    2019-11-11
  • node解析修改nginx配置文件操作实例分析

    node解析修改nginx配置文件操作实例分析

    这篇文章主要介绍了node解析修改nginx配置文件操作,结合实例形式分析了node.js使用nginx-conf解析修改nginx配置文件的相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • NodeJs 包管理工具的使用

    NodeJs 包管理工具的使用

    本文主要介绍了NodeJs 包管理工具,主要包括npm,cnpm及yarn,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • Nodejs使用winston进行日志记录详解

    Nodejs使用winston进行日志记录详解

    在生产环境中,更常见的做法是使用专门的日志记录库,如winston、log4js等,来实现更灵活和可配置的日志记录功能,本篇文章将介绍的是winston的强大的日志记录功能,快跟随小编一起学习一下吧
    2024-01-01
  • nodeJS进程管理器pm2的使用

    nodeJS进程管理器pm2的使用

    这篇文章主要介绍了nodeJS进程管理器pm2的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • node.js用fs.rename强制重命名或移动文件夹的方法

    node.js用fs.rename强制重命名或移动文件夹的方法

    本篇文章主要介绍了node.js用fs.rename强制重命名或移动文件夹的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • node.js中的fs.truncateSync方法使用说明

    node.js中的fs.truncateSync方法使用说明

    这篇文章主要介绍了node.js中的fs.truncateSync方法使用说明,本文介绍了fs.truncateSync的方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下
    2014-12-12

最新评论