-
微信小程序登录功能
2019-08-08 10:54:40新用户登录 忘记密码 2.login.wxss .container { display: flex; flex-direction: column; min-height: 100%; justify-content: space-between; } .page-header { font-size: 32px; ...0.后台数据准备
app.get("/Login",(req,res)=>{ if(req.query.email!=''&&req.query.password!=''){ var status =1 }else{ var status = 0 } var LoginStatus = { LoginStatus:status} res.send(LoginStatus); });
1.login.wxml
<!--logs.wxml--> <view class="page"> <view class="page__hd"> <view class="section__ctn"> <image style="height:50px;width:50px;" src="http://127.0.0.1:3000/img/icon/icon02.png"></image> </view> </view> <view class="page__bd"> <view class="section"> <!-- bindinput获取输入的值 --> <input type="text" bindinput="bindEmailInput" placeholder="邮箱" auto-focus /> </view> <view class="section"> <input type="password" bindinput="bindPasswordInput" placeholder="密码" /> </view> <view class="section"> <view class="btn-area"> <button type="primary" bindtap="login">登录</button> </view> </view> <view class="section"> <view class="btn-area"> <button type="default" bindtap="gotoregister">新用户登录</button> </view> </view> <view class="section"> <view class="btn-area"> <button type="default" bindtap="forgetpassword">忘记密码</button> </view> </view> </view> </view>
2.login.wxss
.container { display: flex; flex-direction: column; min-height: 100%; justify-content: space-between; } .page-header { font-size: 32px; color: #aaa; margin-top: 50rpx; flex-direction: column; align-items: center; } .page-header-text { padding: 20rpx 40rpx; } .page-header-line { width: 150rpx; height: 1px; border-bottom: 1px solid #ccc; } .page-body { width: 100%; display: flex; flex-direction: column; align-items: center; flex-grow: 1; overflow-x: hidden; } .page-body-wrapper { margin-top: 100rpx; display: flex; flex-direction: column; align-items: center; width: 100%; } .page-body-wrapper form { width: 100%; } .page-body-wording { text-align: center; padding: 200rpx 100rpx; } .page-body-info { display: flex; flex-direction: column; align-items: center; background-color: #fff; margin-bottom: 50rpx; width: 100%; padding: 50rpx 0 150rpx 0; } .page-body-title { margin-bottom: 100rpx; font-size: 32rpx; } .page-body-text { font-size: 30rpx; line-height: 26px; color: #ccc; } .page-body-text-small { font-size: 24rpx; color: #000; margin-bottom: 100rpx; } .page-body-form { width: 100%; background-color: #fff; display: flex; flex-direction: column; width: 100%; border: 1px solid #eee; } .page-body-form-item { display: flex; align-items: center; margin-left: 30rpx; border-bottom: 1px solid #eee; height: 88rpx; font-size: 34rpx; } .page-body-form-key { width: 180rpx; color: #000; } .page-body-form-value { flex-grow: 1; } .page-body-form-value .input-placeholder { color: #b2b2b2; } .page-body-form-picker { display: flex; justify-content: space-between; height: 100rpx; align-items: center; font-size: 36rpx; margin-left: 20rpx; padding-right: 20rpx; border-bottom: 1px solid #eee; } .page-body-form-picker-value { color: #ccc; } .page-body-buttons { width: 100%; } .page-body-button { margin: 25rpx; } .page-body-button image { width: 150rpx; height: 150rpx; } .page-footer { text-align: center; color: #1aad19; font-size: 24rpx; margin: 20rpx 0; } .green{ color: #09BB07; } .red{ color: #F76260; } .blue{ color: #10AEFF; } .yellow{ color: #FFBE00; } .gray{ color: #C9C9C9; } .strong{ font-weight: bold; } .bc_green{ background-color: #09BB07; } .bc_red{ background-color: #F76260; } .bc_blue{ background-color: #10AEFF; } .bc_yellow{ background-color: #FFBE00; } .bc_gray{ background-color: #C9C9C9; } .tc{ text-align: center; } .page input{ padding: 20rpx 30rpx; background-color: #fff; border-bottom: 1px solid #dddddd; } checkbox, radio{ margin-right: 10rpx; } .btn-area{ padding: 0 30px; } .btn-area button{ margin-top: 20rpx; margin-bottom: 20rpx; } .page { min-height: 100%; flex: 1; font-size: 32rpx; font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif; overflow: hidden; } .page__hd{ padding: 50rpx 50rpx 50rpx 50rpx; text-align: center; } .page__title{ display: inline-block; padding: 20rpx 40rpx; font-size: 32rpx; color: #AAAAAA; border-bottom: 1px solid #CCCCCC; } .page__desc{ display: none; margin-top: 20rpx; font-size: 26rpx; color: #BBBBBB; } .section{ margin-bottom: 30rpx; } .section_gap{ padding: 0 30rpx; } .section__title{ margin-bottom: 16rpx; padding-left: 30rpx; padding-right: 30rpx; } .section_gap .section__title{ padding-left: 0; padding-right: 0; }
3.login.js
//logs.js var app = getApp(); Page({ data: { email:'', password: '' }, //邮箱数据绑定 bindEmailInput: function(e){ this.setData({ email:e.detail.value }) }, //密码数据绑定 bindPasswordInput: function (e) { this.setData({ password: e.detail.value }) }, login:function(e){ //加载吐司 wx.showToast({ title: '登录请求中', icon: 'loading', duration: 10000 }); //网络请求开始 wx.request({ url: 'http://127.0.0.1:3000/Login?email=' + this.data.email + '&password=' + this.data.password, header: { 'Content-Type': 'application/json' }, success: function(res){ console.log(res.data); wx.hideToast(); if (res.data.LoginStatus == 1){ //进行一些用户状态的存储 //进行tab的切换 wx.switchTab({ url: '../../pages/index/index', success:function(){ console.log('called switchtab') } }) }else{ wx.showModal({ title: '登录失败', content: '请检查您填写的用户信息', showCancel: false, success: function(res){ //回调函数 console.log(res) } }) } } }) } })
-
微信小程序登录功能实现
2019-08-09 11:00:23微信小程序登录功能实现记录微信小程序登录功能实现
微信小程序可以调用微信登录的接口,直接用微信登录,原本以为很简单,结果没想到平时小小的一个微信登录按钮,却有这么多东西。其实思路也不是很难,只是了解过程就很轻易就可以写出来了。
感觉微信登录涉及很多东西,就想记录一下,不过,我想我的方法应该不是最合理或者安全的,但是,功能是能很好的实现。
#整体思路
首先使用wx.login()方法用code到后台服务器换取openid,不过我为了能检测用户登录状态,我在后台把获取到的openid存入redis中,并设置一个缓存时间,就相当于一个session,然后把所谓的sesisonId送到前端,因为微信小程序没有cooking,但是有本地存储storage,于是,我把sessionId存入到storage中,用来检测。如果redis和storage中session存在,那么用户在登录状态,反之两者中有一个不存在,便不是登录状态。要退出登录状态也很简单,removeStorage()删除storage中的内容就好了。小程序部分
由于小程序最新的补丁,以前的那种进入页面直接跳进授权登录页面是不被允许的,必须使用button来使用微信登录方法。如果要获取用户信息,那么就需要属性
open-type='getUserInfo'
具体信息可以查看微信小程序文档 https://developers.weixin.qq.com/miniprogram/dev/component/button.html
wxml<button class='btn1' open-type='getUserInfo' bindgetuserinfo='doLogin'> <view>微信登录</view>
js
doLogin(e) { wx.login({ success: (res) => { console.log(res); // 获取登录临时凭证 const { code } = res; // 调用后端,获取微信的session_key, wx.request({ //后端url 我的后台是springboot搭建的,也可以是其他的 url: '', method: 'get', data: { code: res.code }, success: res => { // 获取到用户的 sessionId var that = this console.log("用户的sessionId:" + res.data.sessionId); //把获取到的sessionId存入到本地storage中 wx.setStorage({ key: 'sessionId', data: res.data.sessionId, }) wx.getStorage({ key: 'sessionId', success: function (res) { console.log(res.data) }, }) } }); } }) },
后台服务器部分
ComonUtils 后台向微信服务器换取openid,封装url
package com.noname.demo.comment; /** * 封装微信小程序appid, secret js_code 为获得用户openId */ public class ComonUtils { public static StringBuffer appendUrl(String code) { StringBuffer info = new StringBuffer("https://api.weixin.qq.com/sns/jscode2session?"); info.append("appid=").append("wx8d87127163bbef11").append("&"); info.append("secret=").append("9718b02bb9be37ba2eecfdec7ec88c00").append("&"); info.append("js_code=").append(code).append("&"); info.append("grant_type=").append("authorization_code"); return info; } }
RedisOperator
package com.noname.demo.comment; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; /** * @Description: 使用redisTemplate的操作实现类 */ @Component public class RedisOperator { // @Autowired // private RedisTemplate<String, Object> redisTemplate; @Autowired private StringRedisTemplate redisTemplate; // Key(键),简单的key-value操作 /** * 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。 * * @param key * @return */ public long ttl(String key) { return redisTemplate.getExpire(key); } /** * 实现命令:expire 设置过期时间,单位秒 * * @param key * @return */ public void expire(String key, long timeout) { redisTemplate.expire(key, timeout, TimeUnit.SECONDS); } /** * 实现命令:INCR key,增加key一次 * * @param key * @return */ public long incr(String key, long delta) { return redisTemplate.opsForValue().increment(key, delta); } /** * 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key */ public Set<String> keys(String pattern) { return redisTemplate.keys(pattern); } /** * 实现命令:DEL key,删除一个key * * @param key */ public void del(String key) { redisTemplate.delete(key); } // String(字符串) /** * 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key) * * @param key * @param value */ public void set(String key, String value) { redisTemplate.opsForValue().set(key, value); } /** * 实现命令:SET key value EX seconds,设置key-value和超时时间(秒) * * @param key * @param value * @param timeout * (以秒为单位) */ public void set(String key, String value, long timeout) { redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); } /** * 实现命令:GET key,返回 key所关联的字符串值。 * * @param key * @return value */ public String get(String key) { return (String)redisTemplate.opsForValue().get(key); } // Hash(哈希表) /** * 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value * * @param key * @param field * @param value */ public void hset(String key, String field, Object value) { redisTemplate.opsForHash().put(key, field, value); } /** * 实现命令:HGET key field,返回哈希表 key中给定域 field的值 * * @param key * @param field * @return */ public String hget(String key, String field) { return (String) redisTemplate.opsForHash().get(key, field); } /** * 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。 * * @param key * @param fields */ public void hdel(String key, Object... fields) { redisTemplate.opsForHash().delete(key, fields); } /** * 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。 * * @param key * @return */ public Map<Object, Object> hgetall(String key) { return redisTemplate.opsForHash().entries(key); } // List(列表) /** * 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头 * * @param key * @param value * @return 执行 LPUSH命令后,列表的长度。 */ public long lpush(String key, String value) { return redisTemplate.opsForList().leftPush(key, value); } /** * 实现命令:LPOP key,移除并返回列表 key的头元素。 * * @param key * @return 列表key的头元素。 */ public String lpop(String key) { return (String)redisTemplate.opsForList().leftPop(key); } /** * 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。 * * @param key * @param value * @return 执行 LPUSH命令后,列表的长度。 */ public long rpush(String key, String value) { return redisTemplate.opsForList().rightPush(key, value); } }
AppUserModel 封装openid和session_key
package com.noname.demo.entity; public class AppUserModel { String openid; String session_key; public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getSession_key() { return session_key; } public void setSession_key(String session_key) { this.session_key = session_key; } }
LoginController
/** * 获取用户openid, 并将session存入redis,发送到前端 * @param code * @return */ @RequestMapping(value = "/doLogin", method = RequestMethod.GET) public Map<String, Object> appDoLogin(String code){ Map<String, Object> map = new HashMap<>(); if(code == null){ map.put("success", false); return map; } String url = new ComonUtils().appendUrl(code).toString(); RestTemplate restTemplate = new RestTemplate(); //用restTemplate请求url,得到openid和session_key String reponse = restTemplate.getForObject(url, String.class); if(reponse == null){ map.put("success", false); return map; } System.out.println(reponse); String openid = ""; String session_key = ""; String[] strings = reponse.split(","); openid = strings[1].substring(10, strings[1].length()-2); session_key = strings[0].substring(16, strings[0].length()-1); AppUserModel appUserModel = new AppUserModel(); appUserModel.setOpenid(openid); appUserModel.setSession_key(session_key); //将openid和session_key存入redis,之后传到前端的sessionId就是 //"userSession:" + appUserModel.getOpenid() redis.set("userSession:" + appUserModel.getOpenid(), appUserModel.getSession_key(), 60*10); //System.out.println(openid); map.put("sessionId","userSession:" + appUserModel.getOpenid()); map.put("success", true); return map; }
以上小程序登录功能就实现了。
后台代码 https://github.com/d1547156325/orderingSystem -
微信小程序登录功能开发--SpringBoot
2020-04-17 00:48:06目录微信小程序登录功能实现整体思路开始代码部分到了激动人心的后端部分!!给微信服务器发请求开发一个请求工具类开发一个json转实体类的工具类创建接收的model类service代码层 微信小程序登录功能实现 微信小程序...微信小程序登录功能实现
微信小程序可以调用微信登录的接口,直接使用微信登录。思路也不是很难,了解过程就很轻易就可以写出来了。
感觉微信登录涉及很多东西,就想记录一下,不过,我想我的方法应该不是最合理或者安全的,但是,功能是能很好的实现。整体思路
首先小程序端使用wx.login()方法获取到code并发送到后台服务器换取openid,为了能检测用户登录状态,我在后台把获取到的openid存入redis中,并设置一个缓存时间,就相当于一个session,然后把所谓的sesisonId送到前端,因为微信小程序没有cooking,但是有本地存储storage,于是,我把sessionId存入到storage中,用来检测。如果redis和storage中session存在,那么用户在登录状态,反之两者中有一个不存在,便不是登录状态。要退出登录状态也很简单,removeStorage()删除storage中的内容就好了。如果其他业务需要与用户相绑定,我们就可以将用户信息持久化至数据库,每个用户在一个小程序里的openid是唯一的,这是微信官方给我们做好的.所以我们只需要做持久化,具体建表自己摸索吧,实在不行请与我联系.
开始代码部分
我们先来看看微信官方文档.
1.小程序登录流程时序图
解释:
调用- wx.login()获取临时登录凭证code,并回传到开发者服务器。
- 调用code2Session接口,换取用户唯一标识 OpenID和会话密钥 session_key。
- 之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
注意:
-
会话密钥session_key是对用户数据进行加密签名的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
-
临时登录凭证 code 只能使用一次
总结:
小程序端执行wx.login后在回调函数中就能拿到上图的code,然后把这个code传给我们后端程序,后端拿到这个这个code后,可以请求code2Session接口拿到用的openid和session_key,openid是用户在微信中唯一标识,我们就可以把这个两个值(val)存起来,然后返回一个键(key)给小程序端,下次小程序请求我们后端的时候,带上这个key,我们就能找到这个val,就可以,这样就把登入做好了。
wx.login(Object object)
调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等。
参数
Object object属性 类型 默认值 必填 说明 最低版本 timeout number 否 超时时间,单位ms 1.9.90 success function 否 接口调用成功的回调函数 fail function 否 接口调用失败的回调函数 complete function 否 接口调用结束的回调函数(调用成功、失败都会执行) object.success 回调函数
参数
Object res属性 类型 说明 code string 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid 和 session_key 等信息 示例代码
wx.login({ success (res) { if (res.code) { //发起网络请求 wx.request({ url: 'https://test.com/onLogin', data: { code: res.code } }) } else { console.log('登录失败!' + res.errMsg) } } })
到了激动人心的后端部分!!
根据我们的理解,我们是向微信服务器发送请求
请求地址url为:
GET https://api.weixin.qq.com/sns/jscode2sessionappid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
我来解释下请求的参数属性 类型 默认值 必填 说明 appid string 是 小程序 appId secret string 是 小程序 appSecret js_code string 是 登录时获取的 code grant_type string 是 授权类型,此处只需填写 authorization_code 返回值
Object
返回的 JSON 数据包属性 类型 说明 openid string 用户唯一标识 session_key string 会话密钥 unionid string 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明。 errcode number 错误码 errmsg string 错误信息 给微信服务器发请求
先引入两个jar包
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency>
开发一个请求工具类
package com.vx.utils; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; /** * @author zty */ public class HttpClientUtil { public static String doGet(String url, Map<String, String> param) { // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response = null; try { // 创建uri URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); // 创建http GET请求 HttpGet httpGet = new HttpGet(uri); // 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doGet(String url) { return doGet(url, null); } public static String doPost(String url, Map<String, String> param) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 创建参数列表 if (param != null) { List<NameValuePair> paramList = new ArrayList<>(); for (String key : param.keySet()) { paramList.add(new BasicNameValuePair(key, param.get(key))); } // 模拟表单 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); httpPost.setEntity(entity); } // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } public static String doPost(String url) { return doPost(url, null); } public static String doPostJson(String url, String json) { // 创建Httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 创建Http Post请求 HttpPost httpPost = new HttpPost(url); // 创建请求内容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 执行http请求 response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } return resultString; } }
开发一个json转实体类的工具类
package com.vx.utils; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; /** * * @Title: JsonUtils.java * @Package com.lee.utils * @Description: 自定义响应结构, 转换类 * Copyright: Copyright (c) 2016 * Company:Nathan.Lee.Salvatore * * @author zty * @date 2020年4月15日 下午11:05:03 * @version V1.0 */ public class JsonUtils { // 定义jackson对象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 将对象转换成json字符串。 * <p>Title: pojoToJson</p> * <p>Description: </p> * @param data * @return */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 将json结果集转化为对象 * * @param jsonData json数据 * @param clazz 对象中的object类型 * @return */ public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 将json数据转换成pojo对象list * <p>Title: jsonToList</p> * <p>Description: </p> * @param jsonData * @param beanType * @return */ public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List<T> list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }
创建接收的model类
package com.vx.model; import lombok.Data; /** * @author zty * @date 2020/4/15 下午3:55 * @description: */ @Data public class VxSessionModel { private String openid; private String session_key; }
service代码层
- codeForm就传入code,为了进行参数校验,这里使用了类
- 下面代码有两个地方需要自己填写,分别为appid和secret,请自行到微信开发者平台查看
- 我这里返回给前端的sessionid为加密后的openid,具体加密工具类请自行Google.
- 插入用户到数据库用到了消息队列,也可不使用,请自行取舍.
@Transactional @Override public ResultVO vxLogin(CodeForm code, BindingResult bindingResult) { if (bindingResult.hasErrors()) { log.info("参数注意必填项!"); // throw new VxxcxException(400,bindingResult.getFieldError().getDefaultMessage()); return ResultVOUtil.error(bindingResult.getFieldError().getDefaultMessage()); } log.info("vx-login-code: " + code.getCode()); //https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code String url = "https://api.weixin.qq.com/sns/jscode2session"; Map<String, String> param = new HashMap<>(); param.put("appid", "*****"); param.put("secret", "******"); param.put("js_code", code.getCode()); param.put("grant_type", "authorization_code"); String vxResult = HttpClientUtil.doGet(url, param); VxSessionModel model = JsonUtils.jsonToPojo(vxResult, VxSessionModel.class); //重新登录覆盖redis中的数据 assert model != null; if (!isExistOpenid(model.getOpenid())) { User user = new User(); user.setOpenid(model.getOpenid()); user.setNowNum(0); user.setMaxNum(5); user.setCreateTime(DateUtil.getNowDate()); user.setModifyTime(DateUtil.getNowDate()); //fanout 广播 rabbitTemplate.convertAndSend("userInsert","",user); } //将session存入redis redisUtil.set(model.getOpenid(), model.getSession_key(), 60 * 60 * 24 * 3); //返回md5加密后的openid return ResultVOUtil.success(MD5Util.string2MD5(model.getOpenid())); } public boolean isExistOpenid(String openid) { if (userMapper.selectByOpenid(openid) == null) { return false; } return true; } @RabbitListener(bindings = { @QueueBinding( value = @Queue,//创建临时队列 exchange = @Exchange(value = "userInsert", type = "fanout") ) }) public void insertUser(User user){ userMapper.insert(user); log.info("插入新用户"); }
好了,登录就完成了,接下来就是业务开发了…
-
SpringBoot实现微信小程序登录功能
2020-09-30 16:28:26SpringBoot实现微信小程序登录微信小程序登录流程登录流程图前端代码后端代码 微信小程序登录流程 微信小程序官方文档:微信小程序官方文档 第一次学习微信小程序的登录,以前也好奇微信小程序的授权登录是怎么实现的...微信小程序登录流程
微信小程序官方文档:微信小程序官方文档
第一次学习微信小程序的登录,以前也好奇微信小程序的授权登录是怎么实现的,看过官方文档后,这里记录下自己学习小程序登录的实现内容。要是有不对的地方请指出来,这篇文章适合和我一样的小白看。算是简单的入个小门。登录流程图
根据流程图的说明,首先是微信小程序的前端调用wx.login()接口获取到code值,然后前端使用wx.request()或者前端自己封装的请求,来调用后台自己写的登录接口,比如:login接口,后台接收到前端传来的code值后,后台要调用微信接口服务里面的jscode2session接口,官方文档有说明,详情可看官方文档,这个jscode2session接口会返回session_key和openid等值,一般是这二个值,unionid看满足条件返回,然后后端在接收到这2个值后,看根据需要是否要加其他返回值,比如:token等,这里加token就是所说的自定义登录态,然后将这些值返回给前端,前端接收到返回值后,自定义登录态存入storage,大致登录就是这样。
前端代码
这里你最好自己去微信公众平台:微信公众平台上面自己注册一个微信小程序,用的测试号好像没有secret值,所以后台根本没办法正确获取到openid值和session_key值,自己注册了微信小程序后,你会有一个appId和secret这2个值,同时还有密钥,这个以后再说。
这里我是自己用微信开发者工具新建的微信小程序项目,没有加任务的东西,目录如下:
这里再app.js文件加上wx.request()代码,代码如下:
App.js//app.js App({ onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId wx.login({ success (res) { if (res.code) { //发起网络请求 wx.request({ url: 'http://localhost:8080/WXLogin/login?code='+res.code, data: 'code='+res.code, method: "post", success: res => { console.info(res.data); }, fail:res => { console.info("失败"); console.info(res.data); } }) } else { console.log('登录失败!' + res.errMsg) } } }) } }) // 获取用户信息 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 wx.getUserInfo({ success: res => { console.log("成功2!"); // 可以将 res 发送给后台解码出 unionId this.globalData.userInfo = res.userInfo // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } } }) }, globalData: { userInfo: null } })
后端代码
可能需要的依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
后台发送get或者post请求的工具类
WeChatUtil.java 代码如下:package com.bowei.officialwebsite.utils; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; /** * 微信小程序工具类 */ @Slf4j public class WeChatUtil { public static String httpRequest(String requestUrl, String requestMethod, String output) { try { URL url = new URL(requestUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes(StandardCharsets.UTF_8)); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str; StringBuilder buffer = new StringBuilder(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); inputStream.close(); connection.disconnect(); return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 向指定 URL 发送POST方法的请求 * * @param url 发送请求的 URL * @param json 请求参数,请求参数应该是 json 的形式。 * @return 所代表远程资源的响应结果 */ public static String httpPost(String url, JSONObject json) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(json); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result=result.concat(line); } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!" + e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }
在application.yml下配置微信小程序的appId和secret,这样方便以后修改和维护
后端接口代码:
CommonResult 是自己封装好的一个json返回对象,自己封装的会返回code,message,data这三个值,这里你可以直接返回jsonObject。package com.bowei.officialwebsite.controller; import com.alibaba.fastjson.JSONObject; import com.bowei.common.api.CommonResult; import com.bowei.officialwebsite.utils.WeChatUtil; import com.github.pagehelper.util.StringUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Api(tags = "WXLoginController", description = "微信登录模块") @Controller @RequestMapping(value = "/WXLogin") public class WXLoginController { @Value("${wxMini.appId}") public String appId; @Value("${wxMini.secret}") public String secret; @ApiOperation("登录") @RequestMapping(value = "/login",method = RequestMethod.POST) @ResponseBody public CommonResult login(@RequestParam(value = "code", required = false) String code){ System.out.println("code==="+code); if(StringUtil.isEmpty(code)){ return CommonResult.failed("code不能为空!"); } System.out.println("appId="+appId+"|| secret="+secret); //微信接口服务,通过调用微信接口服务中jscode2session接口获取到openid和session_key String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"; String str = WeChatUtil.httpRequest(url, "GET", null); JSONObject jsonObject=JSONObject.parseObject(str); //将token也加进去 先写个假的 jsonObject.put("token","sfskjnkjs3231311"); System.out.println("json="+jsonObject); System.out.println(jsonObject.get("token")); return CommonResult.success(jsonObject); } }
后端打印结果:
前端返回结果:
到这里登录的代码就结束了,这里主要显示后端的代码,毕竟本人是后端,对微信小程序不太熟悉,好了,自己的学习分享就到这里了,希望对各位有帮助吧。
-
微信小程序登录功能代码编写
2020-10-03 10:04:18我现在在自学开发小程序的时候,发现自己不会小程序的登录代码编写,所以就找了其他人写的代码,但是基本都是差不多的,下面是我找的比较详细的微信小程序登陆代码 -
微信小程序登录功能的使用
2018-03-07 00:39:12微信小程序的登录功能主要通过两个步骤实现:先上一张微信官方文档中的时序图一、利用wx.login函数获取用户codewx.login({ success: function(res) { //用户code会被封装在res对象中,通过res.code获取用户的code ... -
java实现微信小程序登录功能
2020-08-10 15:22:21* 微信登录 * * @param code * @param encryptedData * @param iv * @param request * @param response * @return */ @RequestMapping("login") @ResponseBody private Map<String, Object... -
uniapp实现微信小程序登录功能
2020-12-23 13:57:02// 1.wx获取登录用户code uni.login({ provider: 'weixin', success: function(loginRes) { //获取到code 拿着code去请求后台接口换openid和unionid 这里说到unionid只有关联了微信开放平台才会... -
微信小程序登录功能实现(通过用户名和密码)
2019-07-26 18:52:04通常我们在登录微信小程序的时候都是通过授权登录,各种博文上已经有了很多案例,这里记录一下自己实际开发过程中,通过用户名和密码请求登录的流程: 1、获取用户在用户名输入框输入的信息 wxml: <input ... -
微信小程序登录功能wx.login
2019-04-19 16:39:41wx.login(object,object) //index.js Page ( { ...//用户登录凭证,有效期5分钟 ...'登录失败' ...3.session_key是会话秘钥,openid是用户标识符,为了保证安全,session_key不应该下发到小程序中。 -
微信小程序登录功能的前端设计与实现
2020-10-22 18:19:00导语 |登录/注册这模块就像个冰山,我们通常以为它就是「输入账号密码,就完成登录了」,但实际下面还有各种需要考虑的问题。作为应用的基础能力,登录/注册的设计需要有足够的健壮性,避免出现... -
微信小程序登录功能实现及讲解(获取用户唯一标识)附源码
2019-09-21 20:35:19功能:登录实现并获取到用户唯一标识 实现步骤:1.调用微信API wx.login()得到code 2.把得到的code传给后端,在后端请求 ... 3.后端把得到的用户唯一标识(openid)传给前端并在前端...小程序端代码: wx.login({ ... -
微信小程序 简单功能实现
2021-01-03 06:11:35微信小程序 简单功能实现 微信小程序官方开发文档: 微信开发文档 一、获取用户授权 1、点击登录按钮,弹出授权弹窗 具体实现: 首先在button上绑定一个函数,注意,需要同时绑定open-type属性值为”getUserInfo”,否则... -
微信小程序用户登录功能视频专题课程
2019-02-12 16:51:59让大家学会微信小程序中登陆功能的实现,如何获取用户的微信账号相关信息 -
微信小程序登录的实现
2020-10-11 10:54:44开发微信小程序必然会涉及到登录功能的实现,不同的技术团队对微信小程序登录实现的方法也不相同,以下是我做过的微信小程序登录实现思路。 前端在微信小程序的入口方法中通过wx.login()方法获取code,并通过wx.... -
微信小程序开放功能
2019-09-22 01:52:31微信小程序在UI部分沿用了自己weui的基础样式,且由于小程序依托于微信app,这样小程序就的很多api可以以桥接的方式来调用原声接口,包括导航、地图、选择图片、IO、网络、登录、支付等功能必然都... -
微信小程序毕业设计、微信小程序商城毕业设计
2019-07-04 11:36:36该微信小程序商城功能模块包含: 首页、分类、商品详情页面,包含加入购物车、收藏商品、商品评论功能、用户登录、微信登录、订单管理、地址管理;完整的购物流程,商品的加入、编辑、删除、批量选择,收货地址的... -
微信小程序登录注册界面
2019-06-02 21:55:21微信小程序登录注册界面 第一次接触微信小程序的开发,首先就是从前端的界面开始,我要做的是一个农场管理的微信小程序,大致包括登录、注册、主要功能界面这些,这里我就分享一下我的登录注册界面的设计和功能实现... -
微信小程序登录演示-源码
2021-01-27 09:49:19微信小程序登录 demo 小程序登录 demo 分为客户端和服务端两个部分 本项目为小程序客户端, 服务端为 实现功能 支持自定义登录态, 完全清除缓存后依然可以返回正确的用户信息 支持绑定用户信息 (昵称, 头像等) 支持...