前端源码:https://pan.baidu.com/s/1uz2Gm2FMB-8RFVkhlHY3kQ
提取码:zb4w
后端源码:https://pan.baidu.com/s/1iPpLrXzWnpAsk5UsfKesGw
提取码:8bwm
小程序登录
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
- 说明
- 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
- 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key。
- 之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
- 注意事项
- 会话密钥
session_key
是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。- 临时登录凭证 code 只能使用一次
- appId 作用说明
- appid 是微信账号的唯一标识,这个是固定不变的;
如果了解微信公众号开发的就需要注意一下,小程序的appid 和 公众号的appid 是不一致的- session_key 功能说明
微信客户端通过wx.getUserInfo()获取用户的信息
后台有时候也需要获取微信客户端的用户信息,因此,就需要利用session_key这个秘钥来从微信平台中获取
官方文档原文
签名校验以及数据加解密涉及用户的会话密钥 session_key。 开发者应该事先通过 wx.login 登录流程获取会话密钥 session_key 并保存在服务器。为了数据不被篡改,开发者不应该把 session_key 传到小程序客户端等服务器外的环境。
检查登录态是否过期
调用接口获取登录凭证(code)
请求自己小程序服器,并且携带了code,userInfo信息
DROP TABLE IF EXISTS `wx_user`;
CREATE TABLE `wx_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名称',
`password` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
`gender` tinyint(3) NOT NULL DEFAULT 0 COMMENT '性别:0 未知, 1男, 1 女',
`birthday` date NULL DEFAULT NULL COMMENT '生日',
`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最近一次登录时间',
`last_login_ip` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最近一次登录IP地址',
`user_level` tinyint(3) NULL DEFAULT 0 COMMENT '用户层级 0 普通用户,1 VIP用户,2 区域代理用户',
`nickname` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称或网络名称',
`mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户手机号码',
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户头像图片',
`weixin_openid` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '微信登录openid',
`status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '0 可用, 1 禁用, 2 注销',
`add_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`deleted` tinyint(1) NULL DEFAULT 0 COMMENT '逻辑删除',
`share_user_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `user_name`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Compact;
com.github.binarywang
weixin-java-miniapp
3.3.0
oa:
wx:
app-id: wxf23b28b5e4ea4d6a
app-secret: 212621faa31cdf0691367ea45b2b6041
msgDataFormat: JSON
封装oa.wx的数据
@Data
@Configuration
@ConfigurationProperties(prefix = "oa.wx")
public class WxProperties {
/**
* 设置微信小程序的appId
*/
private String appId;
/**
* 设置微信小程序的Secret
*/
private String appSecret;
/**
* 消息数据格式
*/
private String msgDataFormat;
}
注册WxMaService
@Configuration
public class WxConfig {
@Autowired
private WxProperties properties;
@Bean
public WxMaConfig wxMaConfig() {
WxMaInMemoryConfig config = new WxMaInMemoryConfig();
config.setAppid(properties.getAppId());
config.setSecret(properties.getAppSecret());
config.setMsgDataFormat(properties.getMsgDataFormat());
return config;
}
@Bean
public WxMaService wxMaService(WxMaConfig maConfig) {
WxMaService service = new WxMaServiceImpl();
service.setWxMaConfig(maConfig);
return service;
}
}
@RequestMapping("/wx/auth")
public class WxAuthController {
@Autowired
private WxMaService wxService;
@PostMapping("login_by_weixin")
public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
//客户端需携带code与userInfo信息
String code = wxLoginInfo.getCode();
UserInfo userInfo = wxLoginInfo.getUserInfo();
if (code == null || userInfo == null) {
return ResponseUtil.badArgument();
}
//调用微信sdk获取openId及sessionKey
String sessionKey = null;
String openId = null;
try {
WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
sessionKey = result.getSessionKey();//session id
openId = result.getOpenid();//用户唯一标识 OpenID
} catch (Exception e) {
e.printStackTrace();
}
if (sessionKey == null || openId == null) {
log.error("微信登录,调用官方接口失败:{}", code);
return ResponseUtil.fail();
}else{
log.info("openId={},sessionKey={}",openId,sessionKey);
}
//根据openId查询wx_user表
//如果不存在,初始化wx_user,并保存到数据库中
//如果存在,更新最后登录时间
//....
// token
UserToken userToken = null;
try {
userToken = UserTokenManager.generateToken(user.getId());
} catch (Exception e) {
log.error("微信登录失败,生成token失败:{}", user.getId());
e.printStackTrace();
return ResponseUtil.fail();
}
userToken.setSessionKey(sessionKey);
log.info("SessionKey={}",UserTokenManager.getSessionKey(user.getId()));
Map
响应给客户端数据有:
token userInfo
将oa-mini项目导入到微信开发者工具中,这里注意一定要修改appid。
点击"修改",将弹出一个对话框,请在对话框中输入你的小程序测试号appid
user.loginByWeixin(res.userInfo).then(res => {
app.globalData.hasLogin = true;
wx.navigateBack({
delta: 1
})
})
function loginByWeixin(userInfo) {
return new Promise(function(resolve, reject) {
return login().then((res) => {
//登录远程服务器
util.request(api.AuthLoginByWeixin, {
code: res.code,
userInfo: userInfo
}, 'POST').then(res => {
if (res.errno === 0) {
//存储用户信息
wx.setStorageSync('userInfo', res.data.userInfo);
wx.setStorageSync('token', res.data.token);
resolve(res);
} else {
reject(res);
}
})
将userInfo,token数据保存到本地
function request(url, data = {}, method = "GET") {
return new Promise(function (resolve, reject) {
wx.request({
url: url,
data: data,
method: method,
timeout:6000,
header: {
'Content-Type': 'application/json',
'X-OA-Token': wx.getStorageSync('token')
},
如果使用util.request函数,每次请求都会携带’X-OA-Token’: wx.getStorageSync(‘token’);而服器已经保存了所有的token,所以服器通过token区分每个客户端
mysql的utf8编码的一个字符最多3个字节,但是一个emoji表情为4个字节,所以utf8不支持存储emoji表情。但是utf8的超集utf8mb4一个字符最多能有4字节,所以能支持emoji表情的存储。
Linux系统中MySQL的配置文件为my.cnf。
Winows中的配置文件为my.ini。
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8mb4
[mysqld]
#设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\\tools\\mysql-5.7.23-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\\tools\\mysql-5.7.23-winx64\\data
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB