赞
踩
code是用户登录凭证
,个人理解为用户的授权码
(需要用户本人授权给小程序,小程序才有权力获取到你这个用户的数据),code需要由小程序向微信服务器获取。
注意: 每个code只能使用一次,且有效期为5分钟。因此,在使用code进行登录时,需要及时将其转换成用户的openid和session_key等信息,以免出现code过期的情况
openid是用来唯一标识用户的一个字符串。在微信小程序中,每个用户的openid都是唯一的。通过openid,小程序可以获取用户的基本信息,如头像、昵称等。
大概就是,不同的用户,在不同的小程序上会有不同的openid,后台可以通过openid+session_key来对使用本小程序的用户进行标识(某个openid就是某个用户)
注意: 同一个用户在不同的小程序中拥有不同的openid。因此,在开发小程序时,不能使用openid来进行用户的唯一性判断。
步骤分析:
code
授权码。调用wx.request()发送请求并携带code,请求开发者服务器(自己编写的后端服务)。HttpClient
向微信接口服务发送请求
,并携带appId
+appsecret
+code
三个参数。session_key
+opendId
等。opendId是微信用户的唯一标识。yml
项目:
wechat:
appid: ${sky.wechat.appid}
secret: ${sky.wechat.secret}
#**配置为微信用户生成jwt令牌时使用的配置项:**
user-secret-key: itheima
user-ttl: 7200000
user-token-name: authentication
@Data
public class UserLoginDTO implements Serializable {
private String code;
}
返回用户的id , openid,token给前端;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserLoginVO implements Serializable {
private Long id;
private String openid;
private String token;
}
controller层
code
,校验数据;service层
code
,向微信服务器发送请求获取openid
;code
可能是错误的);public class UserController { @Autowired private UserService userService; @Autowired private JwtProperties jwtProperties; @PostMapping("/login") @ApiOperation("微信登录") public Result<UserLoginVO> login(@PathVariable UserLoginDTO userLoginDTO){ log.info("微信用户登录:{}",userLoginDTO.getCode()); User user = userService.wxLogin(userLoginDTO); //登录成功后 为微信用户生成jwt令牌 Map<String, Object> claims = new HashMap<>(); claims.put(JwtClaimsConstant.USER_ID, user.getId()); String token = JwtUtil.createJWT( jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims); UserLoginVO userLoginVO = UserLoginVO.builder() .id(user.getId()) .openid(user.getOpenid()) .token(token) .build(); return Result.success(userLoginVO); } }
public class UserServiceImpl implements UserService { @Autowired private WeChatProperties weChatProperties; @Autowired private UserMapper userMapper; //微信服务接口地址 public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session"; /** * 微信登录 * @param userLoginDTO * @return */ public User wxLogin(UserLoginDTO userLoginDTO) { String openid = getOpenid(userLoginDTO.getCode()); //1、 判断openid是否为空,如果为空表示登录失败,抛出业务异常 if (openid == null) { throw new LoginFailedException(MessageConstant.LOGIN_FAILED); } //2、 判断当前用户是否为新用户 User user = userMapper.getByOpenid(openid); //3、 如果是新用户,自动完成注册 if (user == null) { user = User.builder() .openid(openid) .createTime(LocalDateTime.now()) .build(); userMapper.insert(user); } //4、返回这个用户对象 return user; } /** * 调用微信接口服务,获取微信用户的openid * @param code * @return */ private String getOpenid (String code){ //调用微信接口服务,获得当前微信用户的openid Map<String, String> map = new HashMap<>(); map.put("appid", weChatProperties.getAppid()); map.put("secret", weChatProperties.getSecret()); map.put("js_code", code); map.put("grant_type", "authorization_code"); String json = HttpClientUtil.doGet(WX_LOGIN, map); JSONObject jsonObject = JSON.parseObject(json); String openid = jsonObject.getString("openid"); return openid; } }
mapper 和 service接口就省略啦
mapper的insert记得键入主键的返回useGeneratedKeys=“true”
接着就是设置用户的 jwt令牌拦截器
@Component @Slf4j public class JwtTokenUserInterceptor implements HandlerInterceptor { @Autowired private JwtProperties jwtProperties; /** * 校验jwt * * @param request * @param response * @param handler 目标方法 * @return true ,代表放行, false,表示禁止放行 * @throws Exception */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //判断当前拦截到的是Controller的方法还是其他资源 if (!(handler instanceof HandlerMethod)) { //当前拦截到的不是动态方法,直接放行 return true; } //1、从请求头中获取令牌 因为token存放在请求头中, String token = request.getHeader(jwtProperties.getUserTokenName()); //2、校验令牌 try { log.info("jwt校验:{}", token); Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token); Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString()); log.info("当前用户id:", userId); BaseContext.setCurrentId(userId); //通过LocalThread,把id存到该线程的存储空间中; //3、通过,放行 return true; } catch (Exception ex) { //4、不通过,响应401状态码 response.setStatus(401); return false; } }
WebMvcConfiguration配置拦截器;
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
}
参考链接:https://juejin.cn/post/7212074532340908091
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。