微信小程序官方登录流程图:
参考微信小程序登录官网文档
使用uniapp构建一套代码多端使用的前端框架项目
dateUtil.js:
功能:
1. 时间日期格式化
2. 传入日期是否和当前日期的比较
完整代码:
// 判断传入日期是否和当前日期比较 const judgeDate=(toDate)=>{ return new Date().getTime()-new Date(toDate).getTime(); } var timeFormat = function (msTime) { let time = new Date(msTime); let yy = time.getFullYear(); let MM = time.getMonth() + 1; let dd = time.getDate(); let hh = time.getHours() < 10 ? "0" + time.getHours() : time.getHours(); let min = time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes(); let sec = time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds(); return yy + "-" + MM + "-" + dd + " " + hh + ":" + min + ":" + sec; } export {timeFormat,judgeDate}
requestUtil.js:
功能:
1. 定义公共的url
完整代码:
// 同时发送异步代码的次数 let ajaxTimes = 0; // 定义公共的url const baseUrl = "http://localhost:8866"; /** * 返回baseUrl */ export const getBaseUrl = () => { return baseUrl; } /** * 后端请求工具类 * @param {*} params 请求参数 */ export const requestUtil = (params) => { let header = { ...params.header }; // 拼接header 带上token header["token"] = uni.getStorageSync("token"); ajaxTimes++; // 显示加载中 效果 wx.showLoading({ title: "加载中", mask: true }); var start = new Date().getTime(); // 模拟网络延迟加载 while (true) if (new Date().getTime() - start > 1000 * 1) break; return new Promise((resolve, reject) => { wx.request({ ...params, header: header, url: baseUrl + params.url, success: (result) => { resolve(result.data); }, fail: (err) => { uni.showToast({ icon: 'error', title: '连接服务器失败', duration: 3000 }) reject(err); }, complete: () => { ajaxTimes--; if (ajaxTimes === 0) { // 关闭正在等待的图标 wx.hideLoading(); } } }); }) }
stringUtil.js:
功能:
1. 判断字符串是否为空
完整代码:
//判断字符串是否为空 export const isEmpty = (str) => { if (str === '' || str.trim().length === 0) { return true } else { return false; } }
项目结构:
app.vue中,写两个方法:
携带code参数发送请求给后端来获取token和openid
利用idea工具,使用spring initializr初始化创建一个空的springboot项目
springboot版本选择2.3.2.RELEASE。
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-validation org.springframework.boot spring-boot-devtools runtime true mysql mysql-connector-java runtime com.alibaba druid 1.1.10 com.baomidou mybatis-plus-boot-starter 3.3.2 com.alibaba fastjson 1.2.40 com.auth0 java-jwt 3.2.0 io.jsonwebtoken jjwt 0.9.1 commons-io commons-io 2.5 org.projectlombok lombok true org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 cn.hutool hutool-all 5.3.3 com.github.axet kaptcha 0.0.9 org.apache.httpcomponents httpclient 4.5.2 org.springframework.boot spring-boot-maven-plugin 2.3.2.RELEASE
server: port: 8866 servlet: context-path: / spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db-wxlogin?serverTimezone=Asia/Shanghai username: root password: 123456 mybatis-plus: global-config: db-config: id-type: auto configuration: map-underscore-to-camel-case: true auto-mapping-behavior: full log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath:mapper/*.xml weixin: jscode2sessionUrl: https://api.weixin.qq.com/sns/jscode2session appid: wxa4aa78831ea93858 #修改自己的微信小程序 appId secret: a2efb3b611d96b2dee615b7a4dee451a #修改自己的微信小程序 appSecret
创建名称db-wxlogin的数据库
创建t_wxuserinfo数据表
CREATE TABLE `t_wxuserinfo` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '用户编号', `openid` varchar(30) DEFAULT NULL COMMENT '用户唯一标识', `nick_name` varchar(50) DEFAULT NULL COMMENT '用户昵称', `avatar_url` varchar(200) DEFAULT NULL COMMENT '用户头像图片的 URL', `register_date` datetime DEFAULT NULL COMMENT '注册日期', `last_login_date` datetime DEFAULT NULL COMMENT '最后登录日期', `status` char(1) DEFAULT '1' COMMENT '状态 0 可用 1 封禁', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
对应数据库表t_wxuserinfo
package com.tigerhhzz.springbootvote.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * 微信用户信息实体 * * @author tigerhhzz * @date 2023/5/17 15:34 */ @TableName("t_wxUserInfo") @Data public class WxUserInfo implements Serializable { private Integer id; // 用户编号 private String openid; // 用户唯一标识 private String nickName="微信用户"; // 用户昵称 private String avatarUrl="default.png"; // 用户头像图片的 URL @JsonSerialize(using=CustomDateTimeSerializer.class) private Date registerDate; // 注册日期 @JsonSerialize(using=CustomDateTimeSerializer.class) private Date lastLoginDate; // 最后登录日期 private String status="0"; // 用户状态 状态 0 可用 1 封禁 //查询时,则不返回该字段的值 设置该字段在数据库表中不存在 @TableField(select = false,exist = false) private String code; // 微信用户code 前端传来的 }
package com.tigerhhzz.springbootvote.entity; import java.util.HashMap; import java.util.Map; /** * 页面响应entity * * @author tigerhhzz * @date 2023/5/17 15:34 */ public class R extends HashMap{ private static final long serialVersionUID = 1L; public R() { put("code", 0); } public static R error() { return error(500, "未知异常,请联系管理员"); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } @Override public R put(String key, Object value) { super.put(key, value); return this; } }
package com.tigerhhzz.springbootvote.entity; import io.jsonwebtoken.Claims; /** * jwt验证信息 * * @author tigerhhzz * @date 2023/5/17 17:05 */ public class CheckResult { private int errCode; private boolean success; private Claims claims; public int getErrCode() { return errCode; } public void setErrCode(int errCode) { this.errCode = errCode; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public Claims getClaims() { return claims; } public void setClaims(Claims claims) { this.claims = claims; } }
package com.tigerhhzz.springbootvote.properties; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 微信小程序配置文件 * * @author tigerhhzz * @date 2023/5/17 16:55 */ @Component @ConfigurationProperties(prefix = "weixin") @Data public class WeixinProperties { private String jscode2sessionUrl; // 登录凭证校验请求地址 private String appid; // 小程序 appId private String secret; // 小程序 appSecret }
package com.tigerhhzz.springbootvote.util; import java.text.SimpleDateFormat; import java.util.Date; /** * 日期工具类 * * @author tigerhhzz * @date 2023/5/17 15:34 */ public class DateUtil { /** * 日期对象转字符串 * @param date * @param format * @return */ public static String formatDate(Date date,String format){ String result=""; SimpleDateFormat sdf=new SimpleDateFormat(format); if(date!=null){ result=sdf.format(date); } return result; } /** * 字符串转日期对象 * @param str * @param format * @return * @throws Exception */ public static Date formatString(String str,String format) throws Exception{ if(StringUtil.isEmpty(str)){ return null; } SimpleDateFormat sdf=new SimpleDateFormat(format); return sdf.parse(str); } public static String getCurrentDateStr(){ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddhhmmssSSSSSSSSS"); return sdf.format(date); } public static String getCurrentDatePath()throws Exception{ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/"); return sdf.format(date); } public static void main(String[] args) { try { System.out.println(getCurrentDateStr()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.tigerhhzz.springbootvote.util; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; 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.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.conn.util.PublicSuffixMatcherLoader; 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; import org.springframework.stereotype.Component; import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * httpClient 工具类 * * @author tigerhhzz * @date 2023/5/17 15:34 */ @Component public class HttpClientUtil { /** * 默认参数设置 * setConnectTimeout:设置连接超时时间,单位毫秒。 * setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。 * setSocketTimeout:请求获取数据的超时时间,单位毫秒。访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 暂时定义15分钟 */ private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(600000).setConnectTimeout(600000).setConnectionRequestTimeout(600000).build(); /** * 静态内部类---作用:单例产生类的实例 * @author Administrator * */ private static class LazyHolder { private static final HttpClientUtil INSTANCE = new HttpClientUtil(); } private HttpClientUtil(){} public static HttpClientUtil getInstance(){ return LazyHolder.INSTANCE; } /** * 发送 post请求 * @param httpUrl 地址 */ public String sendHttpPost(String httpUrl) { HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost return sendHttpPost(httpPost); } /** * 发送 post请求 * @param httpUrl 地址 * @param params 参数(格式:key1=value1&key2=value2) */ public String sendHttpPost(String httpUrl, String params) { HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost try { //设置参数 StringEntity stringEntity = new StringEntity(params, "UTF-8"); stringEntity.setContentType("application/x-www-form-urlencoded"); httpPost.setEntity(stringEntity); } catch (Exception e) { e.printStackTrace(); } return sendHttpPost(httpPost); } /** * 发送 post请求 * @param httpUrl 地址 * @param maps 参数 */ public String sendHttpPost(String httpUrl, Mapmaps) { HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost // 创建参数队列 List nameValuePairs = new ArrayList (); for (String key : maps.keySet()) { nameValuePairs.add(new BasicNameValuePair(key, maps.get(key))); } try { httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8")); } catch (Exception e) { e.printStackTrace(); } return sendHttpPost(httpPost); } /** * 发送Post请求 * @param httpPost * @return */ private String sendHttpPost(HttpPost httpPost) { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; HttpEntity entity = null; String responseContent = null; try { // 创建默认的httpClient实例 httpClient = HttpClients.createDefault(); httpPost.setConfig(requestConfig); // 执行请求 long execStart = System.currentTimeMillis(); response = httpClient.execute(httpPost); long execEnd = System.currentTimeMillis(); System.out.println("=================执行post请求耗时:"+(execEnd-execStart)+"ms"); long getStart = System.currentTimeMillis(); entity = response.getEntity(); responseContent = EntityUtils.toString(entity, "UTF-8"); long getEnd = System.currentTimeMillis(); System.out.println("=================获取响应结果耗时:"+(getEnd-getStart)+"ms"); } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭连接,释放资源 if (response != null) { response.close(); } if (httpClient != null) { httpClient.close(); } } catch (IOException e) { e.printStackTrace(); } } return responseContent; } /** * 发送 get请求 * @param httpUrl */ public String sendHttpGet(String httpUrl) { HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求 return sendHttpGet(httpGet); } /** * 发送 get请求Https * @param httpUrl */ public String sendHttpsGet(String httpUrl) { HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求 return sendHttpsGet(httpGet); } /** * 发送Get请求 * @param httpGet * @return */ private String sendHttpGet(HttpGet httpGet) { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; HttpEntity entity = null; String responseContent = null; try { // 创建默认的httpClient实例. httpClient = HttpClients.createDefault(); httpGet.setConfig(requestConfig); // 执行请求 response = httpClient.execute(httpGet); entity = response.getEntity(); responseContent = EntityUtils.toString(entity, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭连接,释放资源 if (response != null) { response.close(); } if (httpClient != null) { httpClient.close(); } } catch (IOException e) { e.printStackTrace(); } } return responseContent; } /** * 发送Get请求Https * @param httpGet * @return */ private String sendHttpsGet(HttpGet httpGet) { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; HttpEntity entity = null; String responseContent = null; try { // 创建默认的httpClient实例. PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString())); DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher); httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build(); httpGet.setConfig(requestConfig); // 执行请求 response = httpClient.execute(httpGet); entity = response.getEntity(); responseContent = EntityUtils.toString(entity, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭连接,释放资源 if (response != null) { response.close(); } if (httpClient != null) { httpClient.close(); } } catch (IOException e) { e.printStackTrace(); } } return responseContent; } /** * 发送xml数据 * @param url * @param xmlData * @return * @throws ClientProtocolException * @throws IOException */ public static HttpResponse sendXMLDataByPost(String url, String xmlData) throws ClientProtocolException, IOException { HttpClient httpClient = HttpClients.createDefault(); HttpPost httppost = new HttpPost(url); StringEntity entity = new StringEntity(xmlData); httppost.setEntity(entity); httppost.setHeader("Content-Type", "text/xml;charset=UTF-8"); HttpResponse response = httpClient.execute(httppost); return response; } /** * 获得响应HTTP实体内容 * * @param response * @return * @throws IOException * @throws UnsupportedEncodingException */ public static String getHttpEntityContent(HttpResponse response) throws IOException, UnsupportedEncodingException { HttpEntity entity = response.getEntity(); if (entity != null) { InputStream is = entity.getContent(); BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8")); String line = br.readLine(); StringBuilder sb = new StringBuilder(); while (line != null) { sb.append(line + "\n"); line = br.readLine(); } return sb.toString(); } return ""; } }
package com.tigerhhzz.springbootvote.util; import com.tigerhhzz.springbootvote.constant.JwtConstant; import com.tigerhhzz.springbootvote.entity.CheckResult; import io.jsonwebtoken.*; import org.bouncycastle.util.encoders.Base64; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Date; /** * jwt加密和解密的工具类 * * @author tigerhhzz * @date 2023/5/17 15:34 */ public class JwtUtils { /** * 签发JWT * @param id * @param subject 可以是JSON数据 尽可能少 * @param ttlMillis * @return */ public static String createJWT(String id, String subject, long ttlMillis) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); SecretKey secretKey = generalKey(); JwtBuilder builder = Jwts.builder() .setId(id) .setSubject(subject) // 主题 .setIssuer("tigerhhzz") // 签发者 .setIssuedAt(now) // 签发时间 .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙 if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date expDate = new Date(expMillis); builder.setExpiration(expDate); // 过期时间 } return builder.compact(); } /** * 生成jwt token * @param username * @return */ public static String genJwtToken(String username){ return createJWT(username,username,60*60*1000); } /** * 验证JWT * @param jwtStr * @return */ public static CheckResult validateJWT(String jwtStr) { CheckResult checkResult = new CheckResult(); Claims claims = null; try { claims = parseJWT(jwtStr); checkResult.setSuccess(true); checkResult.setClaims(claims); } catch (ExpiredJwtException e) { checkResult.setErrCode(JwtConstant.JWT_ERRCODE_EXPIRE); checkResult.setSuccess(false); } catch (SignatureException e) { checkResult.setErrCode(JwtConstant.JWT_ERRCODE_FAIL); checkResult.setSuccess(false); } catch (Exception e) { checkResult.setErrCode(JwtConstant.JWT_ERRCODE_FAIL); checkResult.setSuccess(false); } return checkResult; } /** * 生成加密Key * @return */ public static SecretKey generalKey() { byte[] encodedKey = Base64.decode(JwtConstant.JWT_SECERT); SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); return key; } /** * 解析JWT字符串 * @param jwt * @return * @throws Exception */ public static Claims parseJWT(String jwt) { SecretKey secretKey = generalKey(); return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(jwt) .getBody(); } public static void main(String[] args) throws InterruptedException { //小明失效 10s String sc = createJWT("1","小明", 60 * 60 * 1000); System.out.println(sc); System.out.println(validateJWT(sc).getErrCode()); System.out.println(validateJWT(sc).getClaims().getId()); System.out.println(validateJWT(sc).getClaims().getSubject()); //Thread.sleep(3000); System.out.println(validateJWT(sc).getClaims()); Claims claims = validateJWT(sc).getClaims(); String sc2 = createJWT(claims.getId(),claims.getSubject(), JwtConstant.JWT_TTL); System.out.println(sc2); } }
package com.tigerhhzz.springbootvote.util; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * 字符串工具类 * @author * */ public class StringUtil { /** * 判断是否是空 * @param str * @return */ public static boolean isEmpty(String str){ if(str==null||"".equals(str.trim())){ return true; }else{ return false; } } /** * 判断是否不是空 * @param str * @return */ public static boolean isNotEmpty(String str){ if((str!=null)&&!"".equals(str.trim())){ return true; }else{ return false; } } /** * 格式化模糊查询 * @param str * @return */ public static String formatLike(String str){ if(isNotEmpty(str)){ return "%"+str+"%"; }else{ return null; } } /** * 过滤掉集合里的空格 * @param list * @return */ public static ListfilterWhite(List list){ List resultList=new ArrayList (); for(String l:list){ if(isNotEmpty(l)){ resultList.add(l); } } return resultList; } /** * 去除html标签 */ public static String stripHtml(String content) { // 段落替换为换行 content = content.replaceAll("
", "\r\n"); //
替换为换行 content = content.replaceAll("
", "\r\n"); // 去掉其它的<>之间的东西 content = content.replaceAll("\\<.*?>", ""); // 去掉空格 content = content.replaceAll(" ", ""); return content; } /** * 生成六位随机数 * @return */ public static String genSixRandomNum(){ Random random = new Random(); String result=""; for (int i=0;i<6;i++) { result+=random.nextInt(10); } return result; } /** * 生成由[A-Z,0-9]生成的随机字符串 * @param length 欲生成的字符串长度 * @return */ public static String getRandomString(int length){ Random random = new Random(); StringBuffer sb = new StringBuffer(); for(int i = 0; i < length; ++i){ int number = random.nextInt(2); long result = 0; switch(number){ case 0: result = Math.round(Math.random() * 25 + 65); sb.append(String.valueOf((char)result)); break; case 1: sb.append(String.valueOf(new Random().nextInt(10))); break; } } return sb.toString(); } }
微信用户mapper —WxUserInfoMapper
package com.tigerhhzz.springbootvote.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.tigerhhzz.springbootvote.entity.WxUserInfo; import org.springframework.stereotype.Repository; /** * 微信用户mapper * * @author tigerhhzz * @date 2023/5/17 15:26 */ @Repository public interface WxUserInfoMapper extends BaseMapper{ }
微信用户Service接口 —WxUserInfoService
package com.tigerhhzz.springbootvote.service; import com.baomidou.mybatisplus.extension.service.IService; import com.tigerhhzz.springbootvote.entity.WxUserInfo; /** * 微信用户Service接口 * * @author tigerhhzz * @date 2023/5/17 15:34 */ public interface WxUserInfoService extends IService{ }
WxUserInfoServiceImpl---- 实现WxUserInfoService 接口,并继承ServiceImpl实现类的泛型WxUserInfoMapper和WxUserInfo。
package com.tigerhhzz.springbootvote.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tigerhhzz.springbootvote.entity.WxUserInfo; import com.tigerhhzz.springbootvote.mapper.WxUserInfoMapper; import com.tigerhhzz.springbootvote.service.WxUserInfoService; import org.springframework.stereotype.Service; /** * 微信用户Service实现类 * * @author tigerhhzz * @date 2023/5/17 15:34 */ @Service //("wxUserInfoService") public class WxUserInfoServiceImpl extends ServiceImplimplements WxUserInfoService { //@Autowired //private WxUserInfoMapper wxUserInfoMapper; }
两个控制层请求接口
功能: 通过前端发送请求携带的参数code以及后端配置文件中的微信小程序appid和微信小程序密钥,后端拼接url向微信后台发送请求。
String jscode2sessionUrl=weixinProperties.getJscode2sessionUrl()+"?appid="+weixinProperties.getAppid()+"&secret="+weixinProperties.getSecret()+"&js_code="+wxUserInfo.getCode()+"&grant_type=authorization_code"; // https://api.weixin.qq.com/sns/jscode2session?appid=wxa4de78832ea93858&secret=a2efb3b602d96b2dee615b7a4dee451a&js_code=0b1JwPkl2xqHkb4VEjml2vVdua3JwPkq&grant_type=authorization_code
//后端向微信后台送发请求 获取openid String result = httpClientUtil.sendHttpGet(jscode2sessionUrl); System.out.println(result); //结果:{"session_key":"TPTXzC9MOe1owBJ8zrSWTw==","openid":"o2yqx5PBEW-ezFHA24ASqP0Lk1M0"}
通过拿到的openid,去数据库查询对应用户信息,如果没有openid的用户,进行新增操作;
如果存在openid的用户,进行更新操作。
最后利用jwt工具类生成token,返回前端
// 利用jwt生成token返回到前端 String token = JwtUtils.createJWT(openid, wxUserInfo.getNickName(), JwtConstant.JWT_TTL);
MapresultMap=new HashMap<>(); resultMap.put("token",token); resultMap.put("openid",openid); return R.ok(resultMap);
功能: 通过前端发送请求,请求头中携带token参数,后端接受到token,然后进行token验证,拿到openid,通过openid去数据库中查询用户信息,并返回前端
//token验证 Claims claims = JwtUtils.validateJWT(token).getClaims();
获取当前微信登录用户信息:
WeixinUserController 完整代码:
package com.tigerhhzz.springbootvote.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.tigerhhzz.springbootvote.constant.JwtConstant; import com.tigerhhzz.springbootvote.entity.R; import com.tigerhhzz.springbootvote.entity.WxUserInfo; import com.tigerhhzz.springbootvote.properties.WeixinProperties; import com.tigerhhzz.springbootvote.service.WxUserInfoService; import com.tigerhhzz.springbootvote.util.DateUtil; import com.tigerhhzz.springbootvote.util.HttpClientUtil; import com.tigerhhzz.springbootvote.util.JwtUtils; import com.tigerhhzz.springbootvote.util.StringUtil; import io.jsonwebtoken.Claims; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 微信用户Controller * * @author tigerhhzz * @date 2023/5/17 15:34 */ @RequestMapping("/user") @RestController public class WeixinUserController { @Autowired private WxUserInfoService wxUserInfoService; @Autowired private WeixinProperties weixinProperties; @Autowired private HttpClientUtil httpClientUtil; /** * 微信用户登录 * @return */ @RequestMapping("/wxlogin") public R wxLogin(@RequestBody WxUserInfo wxUserInfo){ //拼接后端发送请求的URL 例如 https://api.weixin.qq.com/sns/jscode2session?appid=wxa4de78832ea93858&secret=a2efb3b602d96b2dee615b7a4dee451a&js_code=0b1JwPkl2xqHkb4VEjml2vVdua3JwPkq&grant_type=authorization_code String jscode2sessionUrl=weixinProperties.getJscode2sessionUrl()+"?appid="+weixinProperties.getAppid()+"&secret="+weixinProperties.getSecret()+"&js_code="+wxUserInfo.getCode()+"&grant_type=authorization_code"; System.out.println(jscode2sessionUrl); //后端向微信后台送发请求 获取openid String result = httpClientUtil.sendHttpGet(jscode2sessionUrl); System.out.println(result); //结果:{"session_key":"TPTXzC9MOe1owBJ8zrSWTw==","openid":"o2yqx5PBEW-ezFHA24ASqP0Lk1M0"} // JSONObject jsonObject= JSON.parseObject(result);//转换成object String openid = jsonObject.get("openid").toString();//获取object中openid字段的值; System.out.println(openid); // 插入用户到数据库 假如说 用户不存在 我们插入用户 如果用户存在 我们更新用户 WxUserInfo resultWxUserInfo = wxUserInfoService.getOne(new QueryWrapper().eq("openid", openid)); if(resultWxUserInfo==null){ System.out.println("不存在 插入用户"); wxUserInfo.setOpenid(openid); wxUserInfo.setRegisterDate(new Date()); wxUserInfo.setLastLoginDate(new Date()); wxUserInfoService.save(wxUserInfo); }else{ System.out.println("存在 更新用户"); // resultWxUserInfo.setNickName(wxUserInfo.getNickName()); // resultWxUserInfo.setAvatarUrl(wxUserInfo.getAvatarUrl()); resultWxUserInfo.setLastLoginDate(new Date()); wxUserInfoService.updateById(resultWxUserInfo); } if(resultWxUserInfo!=null && resultWxUserInfo.getStatus().equals("1")){ // 被禁用 return R.error(400,"用户被禁用,具体请联系管理员!"); }else{ // 利用jwt生成token返回到前端 String token = JwtUtils.createJWT(openid, wxUserInfo.getNickName(), JwtConstant.JWT_TTL); Map resultMap=new HashMap<>(); resultMap.put("token",token); resultMap.put("openid",openid); return R.ok(resultMap); } } /** * 获取当前用户信息 * @return */ @RequestMapping("/getUserInfo") public R getUserInfo(@RequestHeader String token){ System.out.println("/getUserInfo----token="+token); Claims claims = JwtUtils.validateJWT(token).getClaims(); System.out.println("openid="+claims.getId()); WxUserInfo currentUser = wxUserInfoService.getOne(new QueryWrapper ().eq("openid", claims.getId())); Map map=new HashMap<>(); map.put("currentUser",currentUser); return R.ok(map); } }
前端源码下载地址 https://download.csdn.net/download/weixin_43025151/87803315
后端源码下载地址:https://download.csdn.net/download/weixin_43025151/87803318