微信小程序登录 后端对code的处理(附代码)
概述
最近工作负责的的项目是一个微信小程序,后端使用的是SpringBoot,给大家分享一下SpringBoot拿到前端传过来的code,如何处理最终返回给前端一个唯一标识token。
逻辑
1. 获取code
code是什么呢?大家可以看一下下面的图。

之前的文章也讲过这个图,前端需要先调用wx.login()方法来获取code,它的作用是让后端给微信的服务端发送请求,获取用户的唯一标识openId,以及session_key。openId是每个微信用户都拥有的一个唯一标识,我们可以用它来存储用户的登录状态,以及识别用户身份,但是最好不要直接使用openId,建议在使用的时候采用一些加密算法。session_key是微信服务端生成的临时会话密钥,用于加密 / 解密用户敏感数据,以及验证用户数据的完整性。
/**
* 登录认证接口
* @param code
* @return jwt
*/
@GetMapping("/login/{code}")
public Response<ClientUserLoginVO> login(@PathVariable String code) {
log.info("code:{}", code);
ClientUserLoginVO clientUserLoginVO = null;
try {
clientUserLoginVO = clientUserService.getUserToken(code);
} catch (Exception e) {
e.printStackTrace();
return Response.<ClientUserLoginVO>builder()
.code(ResponseCode.FAIL.getCode())
.info(e.toString())
.build();
}
log.info("生成ClientUserLoginVO:{}", clientUserLoginVO);
return Response.<ClientUserLoginVO>builder()
.code(ResponseCode.SUCCESS.getCode())
.info(ResponseCode.SUCCESS.getInfo())
.data(clientUserLoginVO)
.build();
}
2. 获取openId和session_key
ok,那么后端获取到code之后,就可以使用code,appid,appSecret去向微信服务器发送请求去获得openId和session_key,其中openId就是我们用来标识用户身份的一个值。

(appId,appSecret需要到微信公众平台获取)
https://mp.weixin.qq.com/
https://mp.weixin.qq.com/![]()
这里我编写了一个获取openId的方法,由于项目中没有用到session_key去解密信息,信息是需要用户填写的,所以我就没存。
public String getUserOpenId(String code) {
Map<String, String> buildParams = buildParams(code);
String url = "https://api.weixin.qq.com/sns/jscode2session";
String result = HttpClientUtil.sendPost(url, buildParams);
if (result == null) {
throw new RuntimeException("获取openId失败");
}
log.info("post请求获取结果: {}", result);
// 解析出openId
JSONObject jsonObject = JSONObject.parseObject(result);
String openid = jsonObject.getString("openid");
return openid;
}
private Map<String, String> buildParams(String code) {
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put("appid", appid);
paramsMap.put("secret", appsecret);
paramsMap.put("js_code", code);
paramsMap.put("grant_type", "authorization_code");
return paramsMap;
}
既然需要向微信服务端发请求,那我们就先把参数装到一个Map当中,在接下来发请求的时候使用,构建好请求参数,接下来我们就要去发送请求获取openId
发送请求获取openId的代码如下:
public static String sendPost(String url, Map<String, String> params) {
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
// 将Map<String, String>类型的参数转换为 HttpClient 需要的List<NameValuePair>类型, NameValuePair是键值对接口,BasicNameValuePair是其基本实现类
List<NameValuePair> urlParameters = params.entrySet().stream()
.map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
try {
httpPost.setEntity(new UrlEncodedFormEntity(urlParameters, StandardCharsets.UTF_8));
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (null != entity) {
return new BufferedReader(new InputStreamReader(entity.getContent())).lines()
.collect(Collectors.joining("\n"));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
这里我们用的HttpClient来发送请求,获得结果字符串
我们再将结果字符串,变成json对象,从里面拿到openId,这里也可以获取session_key。
3. 对openId 进行处理
拿到openId之后,我们就需要将他存储起来,他就是用户的唯一标识,我们要进行关联存储,这里我为用户添加了一个字段交userId,来存储一个与openId相关的值,openId是每个用户在微信服务端的唯一标识,所以这里我没有直接存储,而是进行了AES对称加密,在存储到userId上

这里大家可以自己采取办法处理一下,AES加密后面文章我也会给大家分享一下。
4. 构建jwt返回给前端
经过加密之后我们就得到了真正存储到数据库的userId唯一标识,这时候我们就可以构建jwt,来返回给前端了

/**
* 生成JWT
* @Param dataMap 数据载荷
*/
public String createJWT(Map<String, Object> payload) {
// JWT头部信息【header】
Map<String, Object> header = new HashMap<>();
header.put("alg", alg);
header.put("typ", typ);
// 声明token失效时间(这部分也会放到数据载荷部分), 默认为24小时
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 60*60*24);
// 生成token
String token = Jwts.builder()
.setHeader(header)
.setClaims(payload)
.setExpiration(instance.getTime())
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
return token;
}
/**
* 从jwt中解析出数据载荷
* @return
*/
public JWTDTO parseJWT(String jwt) {
JWTDTO jwtdto = new JWTDTO();
// 解析payload
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(jwt)
.getBody();
jwtdto.setUserId((String) claims.get("userId"));
jwtdto.setExpireTime(claims.getExpiration());
return jwtdto;
}
这里也是直接把jwt解密加密代码给大家

这是alg和typ,需要自己定义一个秘钥secret用来加密与解密
经过这一步骤,我们就可以生成jwt返回给前端了,前端拿到jwt之后,可以将jwt存储到请求头中,接下来后端编写拦截器来判断用户是否携带有效jwt,没有则拦截,让用户进行登录。
(当然这里jwt是有时间的,过期就无效了,大家可以想一想jwt滑动刷新如何实现)
到这里后端就处理完code生成了jwt可以返回给前端啦。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)