【JWT】SpringBoot+微信小程序根据指定参数生成Token、更新Token、判断Token是否已经过期、封装wx.request请求更新Token并判断Token是否过期

这篇具有很好参考价值的文章主要介绍了【JWT】SpringBoot+微信小程序根据指定参数生成Token、更新Token、判断Token是否已经过期、封装wx.request请求更新Token并判断Token是否过期。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、生成Token、更新Token、判断Token是否过期工具类

package com.ckm.ball.utils;
import java.util.Base64;
import java.util.Date;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;

public class JwtUtilChat {

    private static final String SECRET_KEY = "secret"; // 秘钥
    private static final long VALID_TIME = 30 * 60 * 1000; // 有效时间30分钟

    /**
     * 生成Token
     * @param openId 用户唯一标识
     * @return Token
     */
    public static String generateToken(String openId) {
        Date now = new Date();
        Date expireTime = new Date(now.getTime() + VALID_TIME);
        byte[] secretBytes = Base64.getEncoder().encode(SECRET_KEY.getBytes());
        JwtBuilder builder = Jwts.builder()
                .setId(openId)
                .setIssuedAt(now)
                .setExpiration(expireTime)
                .setSubject("jwt")
                .signWith(SignatureAlgorithm.HS256, secretBytes);
        return builder.compact();
    }

    /**
     * 更新Token
     * @param token 原始Token
     * @return 新的Token
     * @throws SignatureException 无效Token异常
     */
    public static String refreshToken(String token) throws SignatureException {
        Claims claims = Jwts.parser()
                .setSigningKey(Base64.getEncoder().encode(SECRET_KEY.getBytes()))
                .parseClaimsJws(token)
                .getBody();
        Date now = new Date();
        Date expireTime = new Date(now.getTime() + VALID_TIME);
        JwtBuilder builder = Jwts.builder()
                .setId(claims.getId())
                .setIssuedAt(now)
                .setExpiration(expireTime)
                .setSubject("jwt")
                .signWith(SignatureAlgorithm.HS256, Base64.getEncoder().encode(SECRET_KEY.getBytes()));
        return builder.compact();
    }

    /**
     * 验证Token是否过期 如果返回false则代表token没有过期,如果返回true则代表token已经过期
     * @param token 要验证的Token
     * @return 是否过期
     * @throws SignatureException 无效Token异常
     */
    public static boolean isTokenExpired(String token) throws SignatureException {
        Claims claims = Jwts.parser()
                .setSigningKey(Base64.getEncoder().encode(SECRET_KEY.getBytes()))
                .parseClaimsJws(token)
                .getBody();
        return claims.getExpiration().before(new Date());
    }
    
    /**
    * 根据Token获取openId
    * @param token 要解析的Token
    * @return openId
    * @throws SignatureException 无效Token异常
    */
    public static String getOpenIdFromToken(String token) throws SignatureException {
        Claims claims = Jwts.parser()
                .setSigningKey(Base64.getEncoder().encode(SECRET_KEY.getBytes()))
                .parseClaimsJws(token)
                .getBody();
        return claims.getId();
    }
    
}

2、微信小程序登录生成Token

微信小程序js代码

微信小程序点击登录按钮调用该方法

login() {
  let that = this
  //调用wx登录接口获取openId
  wx.login({
    success: (res) => {
      //调用getUserCode获取openId
      getUserCode(res.code).then((data) => {
        //生成Token
        userLogin(data.openid).then((result) => {
          that.setData({
            userInfo: result
          })
          //保存到缓存中,后续做判断
          wx.setStorageSync('userInfo', result)
          wx.showLoading()
          setTimeout(function () {
            wx.hideLoading()
            wx.navigateBack({
              delta: 0,
            })
          }, 500)
        })
      })
    },
  })
},

java后端代码

  • getUserCode方法为获取用户的唯一标识openId
  • userLogin方法用于用户授权登录并获取Token
@ApiOperation(value = "获取用户openId",tags = "用户接口")
@GetMapping(value="/getUserCode")
public JSONObject getUserCode(@RequestParam("code") String code){
    System.out.println(code);
    JSONObject jsonObject = new JSONObject();
    try{
        if(code == null || code.equals("")){
            jsonObject.put("errcode","10001");
            jsonObject.put("errmsg","数据传输错误,code为空");
            return jsonObject;
        }
        Map<String, String> data = new HashMap<String, String>();
        data.put("appid", "wx4ab3xxxxxxxx52b");
        data.put("secret", "33ae24be19xxxxxxxxxx77b990");
        data.put("js_code", code);
        data.put("grant_type", "authorization_code");
        String response = HttpRequest.get("https://api.weixin.qq.com/sns/jscode2session").form(data).body();
        jsonObject = JSON.parseObject(response);
        jsonObject.remove("session_key"); //删除session_key 避免泄露用户信息
    }catch (Exception ex){
        jsonObject.put("errcode","10004");
        jsonObject.put("errmsg","获取失败,发生未知错误");
    }
    System.out.println(jsonObject);
    return jsonObject;
}

@GetMapping("/userLogin")
@ApiOperation(value = "用户登录",tags = "用户接口")
public BallUserVo userLogin(@RequestParam("openId") String openId){
    return ballUserService.userLogin(openId);
}

userLogin实现类方法

@Override
public BallUserVo userLogin(String openId) {
    //根据openId生成Token
    String token = JwtUtilChat.generateToken(openId);
    BallUser ballUser = this.getOne(new LambdaQueryWrapper<BallUser>().eq(BallUser::getOpenId, openId));
    //没有记录,首次授权登录
    if (ObjectUtils.isEmpty(ballUser)){
        BallUser newBallUser = new BallUser();
        newBallUser.setCreateTime(new Date());
        newBallUser.setAvatarUrl(avatarUrl);
        newBallUser.setNickName("微信用户"+RandomStringGenerator.generateRandomString());
        newBallUser.setOpenId(openId);
        this.save(newBallUser);

        BallUserVo ballUserVo = new BallUserVo();
        //token赋值
        ballUserVo.setToken(token);
        BeanUtils.copyProperties(newBallUser,ballUserVo);
        return ballUserVo;
    }
    BallUserVo ballUserVo = new BallUserVo();
    //token赋值
    ballUserVo.setToken(token);
    BeanUtils.copyProperties(ballUser,ballUserVo);
    return ballUserVo;
}

3、微信小程序每次发起请求更新Token

封装了wx的request请求,每次发起请求的时候都走一遍更新Token的接口/user/updateTokenTime,如果接口返回offline则代表已经过期,则跳转到登录页面,否则就是没有过期,则更新缓存userInfo中的token。

微信小程序js代码

//经过token验证
function request(options) {
  let userInfo = wx.getStorageSync('userInfo');
  if (userInfo == null || userInfo == undefined || userInfo == '') {
    const userInfoNologin = {
      avatarUrl: "/images/nologin.png",
      nickName: "授权登录"
    };
    wx.setStorageSync('userInfo', userInfoNologin);
    console.log("请登录!");
    wx.navigateTo({
      url: '/pages/login/login',
    });
    return Promise.reject("用户未登录");
  } else {
    const API_ROOT = "http://192.168.1.2:8088";
    return new Promise((resolve, reject) => {
      refreshToken(API_ROOT, userInfo)
        .then(() => {
          wx.request({
            ...options,
            url: API_ROOT + options.url,
            success: function (res) {
              if (res.statusCode === 200) {
                resolve(res.data);
              } else {
                reject(res.errMsg);
              }
            },
            fail: function (err) {
              reject(err.errMsg);
            },
          });
        })
        .catch(error => {
          reject(error);
        });
    });
  }
}

// 更新 Token
function refreshToken(url, userInfo) {
  return new Promise((resolve, reject) => {
    wx.request({
      url: url + "/user/updateTokenTime",
      method: 'GET',
      data: { 'token': userInfo.token },
      success: res => {
        if (res.data == "offline") {
          const userInfoNologin = {
            avatarUrl: "/images/nologin.png",
            nickName: "授权登录"
          };
          
          wx.setStorageSync('userInfo', userInfoNologin);
          wx.navigateTo({
            url: '/pages/login/login',
          });
          
          reject("用户已离线");
        } else {
          userInfo.token = res.data;
          wx.setStorageSync('userInfo', userInfo);
          resolve();
        }
      },
      fail: error => {
        console.log(error);
        reject(error);
      }
    });
  });
}

export default request;

java后端代码

  • updateTokenTime方法用于更新Token并判断原来的Token是否已经过期
 @GetMapping("/updateTokenTime")
 @ApiOperation(value = "更新token",tags = "用户接口")
 public String updateTokenTime(@RequestParam("token") String token){
     return ballUserService.updateTokenTime(token);
 }

updateTokenTime实现类方法

@Override
public String updateTokenTime(String token) {
    // 判断token是否为空
    if (StringUtils.isEmpty(token)) {
        // Token为空,则返回未认证错误
        return "offline";
    }
    try {
        //判断token是否过期,返回false则代表没有过期,反正true则代表过期
        boolean flag = JwtUtilChat.isTokenExpired(token);
        if (!flag){
            // 更新token
            return JwtUtilChat.refreshToken(token);
        }else{
            return "offline";
        }
    }catch (Exception e){
        //异常代表token已经过期
        return "offline";
    }
}

如果你想有一些接口不要经过这个request封装,就比如用户没有登录是可以进入到首页等页面的,开放一些允许用户没有登录状态可以访问的接口。我们可以再封装一个request,专门开放接口不经过Token验证。

//不经过token验证
function onlineRequest(options) {
    const API_ROOT = "http://192.168.1.2:8088";
    return new Promise((resolve, reject) => {
      wx.request({
        ...options,
        url: API_ROOT + options.url, // 在请求的 URL 前加上 API_ROOT
        success: function (res) {
          if (res.statusCode === 200) {
            resolve(res.data);
          } else {
            reject(res.errMsg);
          }
        },
        fail: function (err) {
          reject(err.errMsg);
        },
      });
    });
}
export default onlineRequest;

API怎么编写?

import request from "../../utils/request"; //经过token的封装
import onlineRequest from "../../utils/onlineRequest"; //不经过token的封装

//用户没有登录,但是可以访问这个接口
export function getBallCourtInfoByPoint(lat,lng) {
  return onlineRequest({
    url: '/court/getBallCourtInfoByPoint',
    method: 'get',
    data:{
      lat,
      lng
    }
  });
}

//用户必须登录才能访问这个接口
export function getBallCourtInfoByPointById(id) {
  return request({
    url: '/court/getBallCourtInfoByPointById',
    method: 'get',
    data:{id}
  });
}

接口怎么调用?文章来源地址https://www.toymoban.com/news/detail-766922.html

import {
  getBallCourtInfoByPoint,
  getBallCourtInfoByPointById
} from "../../../api/home/home.js";

getBallCourtInfoByPoint(res){
  let that = this
  //该方法不经过Token验证
  getBallCourtInfoByPoint(res.latitude, res.longitude).then((res) => {
    res.forEach(element => {
      element['id'] = Number(element.id)
      element['markerId'] = Number(element.id)
      element['title'] = element.ballCourtName
      element['width'] = 45
      element['height'] = 45
      element['latitude'] = Number(element.lat)
      element['longitude'] = Number(element.lng)
      element['lat'] = Number(element.lat)
      element['lng'] = Number(element.lng)
      element['iconPath'] = "/images/ball.png"
    });
    that.setData({
      markers: res
    })
  });
},

onMarkerTap(e) {
  let that = this
  console.log(e);
  //该方法经过Token验证
  getBallCourtInfoByPointById(e.detail.markerId).then((res) => {
    that.setData({
      showPopup: true,
      ballCourtInfo: res
    })
  })
}

到了这里,关于【JWT】SpringBoot+微信小程序根据指定参数生成Token、更新Token、判断Token是否已经过期、封装wx.request请求更新Token并判断Token是否过期的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 微信小程序一键登录功能,使用uni-app和springboot(JWT鉴权)

    目录 概述 微信登录接口说明  关于获取微信用户的信息 前端代码(uni-app) 后端代码(SpringBoot) 配置文件:application.yml  配置文件:Pom.xml  类:WeChatModel    类:WeChatSessionModel  类:UserInfoController 业务层实现类:UserInfoServiceImpl 工具类:JWTUtils 拦截器配置-自定义拦截器

    2024年02月09日
    浏览(52)
  • 短信跳转打开微信小程序的指定页面,可以携带参数

    本项目具体需求是短信跳转同一个小程序的不同页面,可以带参数。使用云函数和h5页面,开发时使用静态网站调试,后期h5页面后端另外部署的。 不属于原创,只是在使用的过程中参考以下教程,最终达到效果。现在记录下自己的实施过程。 微信小程序云函数使用教程【超

    2024年04月16日
    浏览(42)
  • 【微信小程序】扫描外部二维码、小程序码进入并获得携带参数,使用参数跳转到指定页面

    您需要使用微信提供的跳转链接和相关参数。以下是实现的步骤: 生成跳转链接:使用以下链接格式生成跳转链接,其中 APPID 是您的小程序的 AppID, PATH 是您要跳转的页面路径, QUERY 是您要传递的参数。 生成二维码:使用生成的跳转链接生成二维码。您可以使用在线的二维

    2024年02月08日
    浏览(45)
  • 微信小程序生成携带参数的二维码

    当对需求的时候发现 要完成一个永久二维码直接进入微信小程序的对应页面+对应IID参数 不要慌 这篇文章解决 满足生成需要 微信官方提供生成微信二维码 可满足大部分功能 获取不限制的小程序码 | 微信开放文档 可以看到官方文档有3种二维码的样式 我们这里以第一种的小

    2024年02月09日
    浏览(37)
  • 微信小程序生成带动态参数二维码

    首先说一下我的使用场景,用户可根据id生成这一条记录的二维码,其他人扫码直接跳转到小程序,显示这条记录的具体信息。 分两步:第一在微信公众号后台配置,第二利用canvas前端实现二维码展示,并接收参数做下一步处理。 登录微信公众平台,依次点击开发管理 - 开发

    2024年02月11日
    浏览(42)
  • 微信小程序中生成普通二维码,并根据二维码里的参数跳转对应的页面

    找到开发目录下面的 》 【开发管理】 》【开发设置】找到【扫普通链接二维码打开小程序】模块, 如图: 点击【添加】 例如: 我的生成二维码的链接地址是 服务器请求地址+需要跳转的参数 第一步:对要传递的参数进行编码 我要跳转到资讯页面, 服务器域名:https://x

    2024年02月08日
    浏览(31)
  • 微信小程序:生成二维码带参数并获取值

    通过后台接口可以获取小程序任意页面的小程序码,需要注意的是 接口只能生成已发布的小程序的二维码 小程序接口文档 1)scene 字段的值会作为 query 参数传递给小程序/小游戏。用户扫描该码进入小程序/小游戏后,开发者可以获取到二维码中的 scene 值,再做处理逻辑。

    2024年02月15日
    浏览(28)
  • 猿创征文|微信小程序扫描二维码如何跳转小程序内指定页面并传递参数给目标页面?

    实际项目中,用户通过扫描打印小票上的二维码,自己实现开具发票功能,那么这里就需要用户在扫描小票二维码后,跳转小程序内添加开票信息并提交后台开具发票的页面。 首先二维码的本质就是一个链接地址。 其次登录微信小程序开放平台,设置 扫普通链接二维码打开

    2023年04月08日
    浏览(38)
  • Taro+vue微信小程序根据字符串生成二维码图片,点击弹出图片,长按保存(可用!!!)

    效果:页面加载时生成二维码,点击二维码弹出图片,长按图片可保存。 借鉴了一个大佬的文章https://www.zhangshengrong.com/p/q0arZ9J4ax/#google_vignette

    2024年02月10日
    浏览(45)
  • uniapp微信小程序 生成小程序码scene参数踩坑全指南@杨章隐

    微信生成二维码官方文档地址:获取小程序码 | 微信开放文档 (qq.com) 这里采用的是 获取不限制的小程序码 注意事项 如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。 POST 参数需要转成 JSON 字符串,不支持 form 表单提交。 调用分钟频率受

    2024年02月06日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包