微信小程序登录流程(包含前端、后端代码)

这篇具有很好参考价值的文章主要介绍了微信小程序登录流程(包含前端、后端代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


theme: channing-cyan

小程序免密登录前端,微信小程序,前端,小程序

一、前言

在微信小程序的开发过程中,如果想要保留用户数据(比如:操作记录购物车信息等等)就必须要用户登陆。为什么呢?比如说,数据库中有一条数据你如何知道这条数据属于谁?属于那个用户呢?这就需要用户登录来获取用户唯一标识从而确定这条数据是属于哪个用户的,那么如何做微信小程序的登陆功能呢?让我们使用Springboot框架+AOP一起来学习吧!


二、流程

微信小程序登录流程:

小程序免密登录前端,微信小程序,前端,小程序

开发者服务器处理流程:

小程序免密登录前端,微信小程序,前端,小程序

1.1 获取用户Code

通过wx.login来获取临时登录code

javascript wx.login({ success (res) { if (res.code) { //发起网络请求 wx.request({ url: 'https://example.com/onLogin', data: { code: res.code } }) } else { console.log('登录失败!' + res.errMsg) } } })

1.2 获取appid

在注册微信开发者账后,可以在微信小程序管理后台获取appid小程序免密登录前端,微信小程序,前端,小程序

1.3 获取appsecret

小程序密钥同样是在注册微信开发者平台账号后,在管理后台获取的: 小程序免密登录前端,微信小程序,前端,小程序 由于微信小程序密钥不以明文的方式展示,如果忘记了,重置下就可以了。

1.4 开发者服务向微信接口服务发起请求

拿着微信codeappidappsecret开发者服务器去请求微信接口服务 换取 openIdsecretKey(这里我们使用ApiPost工具来进行请求,当然PostMan工具也行): 小程序免密登录前端,微信小程序,前端,小程序

调用微信接口服务接口(注意是Get请求):

javascript https://api.weixin.qq.com/sns/jscode2session?

1.5 返回值

java { "session_key": "xxxxx", "openid": "xxxxx" }

拿到返回值后,应该入库,保存一下。 数据库结构如下: 小程序免密登录前端,微信小程序,前端,小程序 等下次该用户登录时,走完1.4流程后,可以根据返回值中的openid在我们库中找到该用户,然后进行后续的操作。

1.6 自定义token

所谓token就是用来确认用户的身份证,拿到下面的返回值后,我们有下面两种方式生成自定义token

(1)使用业务ID生成token(推荐使用,后续的内容都是以用户ID作为例子的):
小程序免密登录前端,微信小程序,前端,小程序

(2)使用session_key生成token

java { "session_key": "xxxxx" }

(3)生成token的工具:

使用md5加密工具来生成token,工具类如下:

```java import cn.hutool.crypto.Mode; import cn.hutool.crypto.Padding; import cn.hutool.crypto.symmetric.AES;

import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets;

public class AESUtil {

/**
 * 加密密钥
 */
private static final String ENCODE_KEY = "test_key_secret_";
/**
 * 偏移量
 */
private static final String IV_KEY = "0000000000000000";

public static String encryptFromString(String data, Mode mode, Padding padding) {
    AES aes;
    if (Mode.CBC == mode) {
        aes = new AES(mode, padding,
                new SecretKeySpec(ENCODE_KEY.getBytes(), "AES"),
                new IvParameterSpec(IV_KEY.getBytes()));
    } else {
        aes = new AES(mode, padding,
                new SecretKeySpec(ENCODE_KEY.getBytes(), "AES"));
    }
    return aes.encryptBase64(data, StandardCharsets.UTF_8);
}

public static String decryptFromString(String data, Mode mode, Padding padding) {
    AES aes;
    if (Mode.CBC == mode) {
        aes = new AES(mode, padding,
                new SecretKeySpec(ENCODE_KEY.getBytes(), "AES"),
                new IvParameterSpec(IV_KEY.getBytes()));
    } else {
        aes = new AES(mode, padding,
                new SecretKeySpec(ENCODE_KEY.getBytes(), "AES"));
    }
    byte[] decryptDataBase64 = aes.decrypt(data);
    return new String(decryptDataBase64, StandardCharsets.UTF_8);
}

} ```

注意:ENCODE_KEY加密密钥不是固定的可以自己设置,但是!!!ENCODE_KEYIV_KEY偏移量的字符数量一定要保持一致!!!否者解密失败!!!

测试:

java String encryptData = AESUtil.encryptFromString("test123456..", Mode.CBC, Padding.ZeroPadding); System.out.println("加密:" + encryptData); String decryptData = AESUtil.decryptFromString(encryptData, Mode.CBC, Padding.ZeroPadding); System.out.println("解密:" + decryptData);

结果:

java 加密:UYKwmVTh39qvwHsQ+tkFow== 解密:test123456..

(5)将生成好的token放入到Redis(不重要,可以省略)

之所以放入Redis是因为它可以设置过期时间,可以实现token过期重新登录的功能。比如:如果接收到微信小程序请求所携带的token后先去Redis查询是否存在,如果不存在则判定过期,直接返回让再次用户登录。

```java @Autowired private RedisTemplate redisTemplate; .... //微信用户的唯一标识 private String userId= 'xxxxx' //将token放入redis并设置3天过期 redisTemplate.opsForValue().set(userId,JSONObject.toJSONString(userInfo),3, TimeUnit.DAYS);

```

(6)返回token给微信小程序

token放到返回体中返回给微信端。

java ... return returnSuccess(token);

1.7 将token放到本地

开发者服务器返回给微信小程序结果后,将token放入到本地存储。

javascript ... //将token放到本地 wx.setStorageSync('token', result.sessionKey) ...

1.8 请求带上token

开发者服务器发起请求时,在header中带上token

javascript ... wx.request({ url: 'https://xxxx.com/api/method', header:{"token":wx.getStorageSync('token')}, success:function(res){}, fail:function(res){} }) ...

1.9 开发者服务器验证token

开发者服务器在接收到微信端发起的业务请求时,通过AOP进行拦截获取header中的token

(1)AOP统一拦截:

使用SpringAOP来拦截请求获取token

java //获取token String token = request.getHeader("token"); log.info("token:{}",token);

(2)解密token

java ... String token = 'xxxx'; log.info("解密前:{}",decryptData); String decryptData = AESUtil.decryptFromString(token, Mode.CBC, Padding.ZeroPadding); log.info("解密结果:{}",decryptData); //拿到用户ID String userId = decryptData; ...

(3)验证是否过期(不重要,可以省略的步骤)

java @Autowired private RedisTemplate redisTemplate; ... //用户ID String userId = decryptData ValueOperations valueOperations = redisTemplate.opsForValue(); String userInfoRedis = (String)valueOperations.get(userId); ...

三、前后端完整代码

2.1 前端代码

(1)登陆

javascript wx.login({ success(res){ if(res.code){ wx.request({ url:'https://xxxx.com/login/wxLogin', method:"POST", data:{"code":res.code} , dataType:"json", success:function(res){ result = res.data.result wx.setStorageSync('token', result.token) //页面跳转 ... }, fail:function(res){}, }) } } })

(2)发起业务请求

javascript wx.request({ url: "https://xxxx.com/test/test", method: "GET", dataType:"json", data:{}, //在heard中戴上token header:{"token":wx.getStorageSync('token')}, success:function(res){ ... }, fail:function(res){} });

2.2 后端代码

后端使用的Java语言,框架是Springboot + AOP实现。 目录结构如下: 小程序免密登录前端,微信小程序,前端,小程序yml配置文件: 小程序免密登录前端,微信小程序,前端,小程序

(1)依赖

```xml org.springframework.boot spring-boot-starter-web 2.1.2.RELEASE

org.springframework.boot spring-boot-starter 2.3.7.RELEASE

org.projectlombok lombok 1.16.16

org.slf4j slf4j-api 1.7.30

cn.hutool hutool-all 5.6.3

org.springframework.boot spring-boot-starter-aop 3.0.4 ```

(2)切面相关代码

```java import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest;

@Aspect @Component @Slf4j public class TestAspect { @Autowired private HttpServletRequest request;

@Pointcut("execution(* xx.xxx.controller.*.*(..))"
          +"&& !execution(* xx.xxx.controller.WxLogin.*(..)"    )
public void pointCut(){}
@Around(value = "pointCut()")
public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
    //获取token
    String token = request.getHeader("token");
    log.info("token:{}",token);
    //不存在token直接抛出异常
    if(StringUtils.isEmpty(token)){
        throw new AopException();
    }
    //解析token
    String userId = AESUtil.decryptFromString(token, Mode.CBC, Padding.ZeroPadding);
    log.info("解析token:{}",userId);
    //将token 放入到 Base基础类
    Base base = new Base();
    base.setUserId(userId);
    //放到Base中
    final Object[] args = joinPoint.getArgs();
    for (Object arg : args) {
        if(arg instanceof Base){
            BeanUtils.copyProperties(base, arg);
        }
    }
    //放到ThreadLocal中
    User user = new User();
    user.setUserId(userId);
    UserContent.setUserContext(user);
    return joinPoint.proceed();
}

@After(value = "pointCut()")
public void controllerAfter() throws Throwable {
    log.info("后置通知");
    log.info("移除ThreadLocal中的用户信息:{}",UserContent.getUserContext());
    UserContent.removeUserContext();
}

}

```

知识点:

从上面代码中我们可以看到。我们通过解密可以拿到UserId,这个值我们是频繁使用的,那么如何做到随用随取呢?

  • 第一种方式:使用Base基础类,然后让Controller需要传递参数的DTO都继承Base然后就可以随时使用UserId了。

  • 第二种方式:使用ThreadLocal,这种是比上一种优雅一些,也可以完全做到随用随取。但是需要注意在会话结束后一定要移除ThreadLocal中的用户信息,否则会导致内存溢出(这很重要),一般使用切面的后置通知来做这件事情。

execution(* xx.xx.controller.*.*(..))解释:在方法执行时,xx.xx.controller包下的所有下面的所有带有任何参数的方法都需要走这个切面。

@PointCut注解值的规则:

  • execution:方法执行时触发。
  • 第一个 *:返回任意类型。
  • xx.xx.controller:具体的报路径。
  • 第二个*:任意类。
  • 第三个*:任意方法。
  • (..):任意参数。

如果想要排除xxController类可以这样写: @Pointcut("execution(* xx.xxx.xxxx.controller..(..)) " + "&& !execution(* xx.xxx.xxxx.controller.xxController.*(..))") 比如 登陆的时候就需要放行登陆的接口。

```java public class AopException extends Exception { public AopException() { super("登录超时,请重新登录"); } }

```

(3)控制层代码

登陆Controller代码:

```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/login") public class WxLogin {

@Autowired
private IWxLoginService iWxLoginService;

@PostMapping("/wxLogin")
public Response wxLogin(@RequestBody WxLoginRequestDto requestDto){
    WxLoginResponseDto wxLoginResponseDto = iWxLoginService.wxLogin(requestDto);
    return returnSuccess(wxLoginResponseDto);
}

}

```

业务逻辑Controller代码:

```java import cn.trueland.model.Base; import cn.trueland.model.UserContent; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;

@RestController @RequestMapping("/test") public class TestController { @GetMapping("/test") public String test(Base base){ return base.getUserId(); } @GetMapping("/test2") public String test2(){ return UserContent.getUserContext().getUserId(); }

}

```

(4)Service层代码:

这里我只帖登陆的Service层代码,业务的没有必要。

java public String wxLogin(WxLoginRequestDto requestDto) { if(StringUtils.isBlank(requestDto.getCode())){ throw new BusinessException("code为空!"); } //获取微信服务接口地址 String authCode2Session = wxConfig.getAuthCode2Session(requestDto.getCode()); //请求微信服务接口获取 openId String result = HttpClientUtil.doGet(authCode2Session); String openId = JSONObject.parseObject(result).getString("openid"); String sessionKey = JSONObject.parseObject(result).getString("session_key"); //入库 并返回 userId (逻辑省略) String userId = ...; //将用户信息存入redis redisTemplate.opsForValue().set(userId,userId ,3, TimeUnit.DAYS); String token = AESUtil.encryptFromString(userId, Mode.CBC, Padding.ZeroPadding); return token; }

(4)实体类相关代码

登录请求DTO:

java import lombok.Data; @Data public class WxLoginRequestDto { /** * code */ private String code; }

基础类Base:

```java import lombok.Data;

@Data public class Base { private String userId; }

`` 用户实体类User`:

```java import lombok.Data;

@Data public class User { private String userId; }

`` 用户信息实体UserContent`:

```java public class UserContent { private static final ThreadLocal userInfo = new ThreadLocal();

public static User getUserContext(){
    return userInfo.get();
}

public static void setUserContext(User userContext){
    userInfo.set(userContext);
}

public static void removeUserContext(){
    userInfo.remove();
}

}

```

(5)配置类

```java import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;

@Data @Component @ConfigurationProperties(prefix = "wx") public class WxConfig { /* * 小程序AppId */ private String appId; /* * 小程序密钥 / private String appSecret; /* * 授权类型 / private String grantType; /* * auth.code2Session 的 url */ private String authCodeSessionUrl; } ```

(6)yml配置信息

xml wx: app-id: xxxx app-secret: xxxx auth-code-session-url: https://api.weixin.qq.com/sns/jscode2session? grant-type: authorization_code

测试结果

小程序免密登录前端,微信小程序,前端,小程序

小程序免密登录前端,微信小程序,前端,小程序 都可以拿到UserId并返回。

下面就可以开心的处理业务逻辑啦!!!文章来源地址https://www.toymoban.com/news/detail-771401.html

到了这里,关于微信小程序登录流程(包含前端、后端代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Gpt微信小程序搭建的前后端流程 - 前端小程序部分-2.确定交互所需的后端API(二)

    Gpt微信小程序搭建的前后端流程 - 前端小程序部分-2.确定交互所需的后端API(二) 参考微信小程序- 小柠AI智能聊天 ,可自行先体验。 根据上一节的小程序静态页面设计,需要从后端获取数据的主要4个点: 登录流程; 获取今日已提问次数; 获取聊天记录; 发起聊天和响应。

    2024年02月13日
    浏览(32)
  • 菜谱微信小程序源码,包含后端业务逻辑

     每日分享两个小程序源码 下载地址:无极低码:wheart.cn          首页代码,更多代码请搜索 无极低码 进行下载

    2024年02月11日
    浏览(30)
  • 【微信小程序】实现微信小程序登录(附源码)后端,微信小程序获取手机号

    登录简介 第一步:获取token 第二步:通过token拿用户信息 第三步:调用接口获取手机号 HttpClientUtil: WeChatUtil: controller层: service层: serviceImpl层: 登录简介        新版本微信小程序登录 是前端获取用户信息,不再是后端获取信息进行保存。所以后端要做的主要流程就是

    2024年04月23日
    浏览(40)
  • 微信小程序接入微信登录后端API

    微信官方文档:小程序登录 | 微信开放文档 (qq.com)   1.前端获取code 获取微信登录code https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html 2.获取微信用户信息 获取微信用户信息 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html 后台我这边是使

    2024年02月04日
    浏览(33)
  • 小程序实现微信登录Java后端(一)--前端实现

    目录 一、概述 二、登录流程 三、前端代码 四、解读前端代码 1、登录部分 2、检查当前用户是否已登录 3、小程序启动时校验登录 五、阶段性小结 最近终于有时间去搞一下准备参加比赛的小程序,小程序一开始设计的是使用邮箱登录,老师建议直接实现微信登录,更加方便

    2024年02月07日
    浏览(34)
  • 微信小程序-微信小程序登录流程(一)

    微信小程序,小程序的一种,英文名Wechat Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用 冷启动: 小程序首次打开或销毁后再次被打开,此时小程序需要重新加载启动,即冷启动。会检查小程序是否

    2024年02月11日
    浏览(30)
  • uniapp 小程序实现微信授权登录(前端和后端)

    1.主要流程:先通过 uni.getUserProfile授权获取用户名称和头像等信息 在调用 uni.login 获取微信登录需要的临时code 2. 前端代码: 1.主要流程:在前端调用接口成功的将临时code 传递给后端时 ,后端通过调用微信的第三方接口拿到 openid, session_key 这两个参数,查询数据库是否有

    2024年02月16日
    浏览(28)
  • 微信小程序获取手机号登录(Java后端)

    1.前端请求getPhoneNumber方法获取code传给后端接口; 2.后端接口通过配置的appid、secretKey请求接口https://api.weixin.qq.com/cgi-bin/token获取access_token参数; 3.后端通过参数code和参数access_token,去请求接口https://api.weixin.qq.com/wxa/business/getuserphonenumber来获取手机号。

    2024年02月11日
    浏览(51)
  • Java 实现微信扫码登录方法(提供前端及后端核心代码)

    思路 1、Vue前端页面获取一个公众号的二维码,不是普通二维号,是带有场景值的 2、java后端接收前端的请求,生成一个带时效性的二维码链接返回给前端 3、公众号平台配置服务器接口地址 4、接收到关注或扫码请求并相应处理 5、前端轮询状态,如果检查到验证通过进到下

    2024年02月19日
    浏览(36)
  • 微信小程序授权登录流程

    我是IT果果日记,微信公众号请搜索 IT果果日记 一个普通的技术宅,定期分享技术文章,欢迎点赞、关注和转发,请多关照。 首先, 我们要了解什么是微信小程序登录?它的作用是什么? 微信小程序登录是为了让开发者的服务器获取用户的openId以及session_key的令牌。 请不要

    2024年02月14日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包