package org.dromara.web.service.impl; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.model.XcxLoginBody; import org.dromara.common.core.domain.model.XcxLoginUser; import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.domain.SysClient; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.web.domain.vo.LoginVo; import org.dromara.web.service.IAuthStrategy; import org.dromara.web.service.SysLoginService; import org.springframework.stereotype.Service; /** * 小程序认证策略 * * @author Michelle.Chung */ @Slf4j @Service("xcx" + IAuthStrategy.BASE_NAME) @RequiredArgsConstructor public class XcxAuthStrategy implements IAuthStrategy { private final SysLoginService loginService; @Override public LoginVo login(String body, SysClientVo client) { XcxLoginBody loginBody = JsonUtils.parseObject(body, XcxLoginBody.class); ValidatorUtils.validate(loginBody); // xcxCode 为 小程序调用 wx.login 授权后获取 String xcxCode = loginBody.getXcxCode(); // 多个小程序识别使用 String appid = loginBody.getAppid(); // todo 以下自行实现 // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid String openid = ""; // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可 SysUserVo user = loadUserByOpenid(openid); // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 XcxLoginUser loginUser = new XcxLoginUser(); loginUser.setTenantId(user.getTenantId()); loginUser.setUserId(user.getUserId()); loginUser.setUsername(user.getUserName()); loginUser.setNickname(user.getNickName()); loginUser.setUserType(user.getUserType()); loginUser.setClientKey(client.getClientKey()); loginUser.setDeviceType(client.getDeviceType()); loginUser.setOpenid(openid); SaLoginModel model = new SaLoginModel(); model.setDevice(client.getDeviceType()); // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 // 例如: 后台用户30分钟过期 app用户1天过期 model.setTimeout(client.getTimeout()); model.setActiveTimeout(client.getActiveTimeout()); model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); // 生成token LoginHelper.login(loginUser, model); LoginVo loginVo = new LoginVo(); loginVo.setAccessToken(StpUtil.getTokenValue()); loginVo.setExpireIn(StpUtil.getTokenTimeout()); loginVo.setClientId(client.getClientId()); loginVo.setOpenid(openid); return loginVo; } private SysUserVo loadUserByOpenid(String openid) { // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户 // todo 自行实现 userService.selectUserByOpenid(openid); SysUserVo user = new SysUserVo(); if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", openid); // todo 用户不存在 业务逻辑自行实现 } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", openid); // todo 用户已被停用 业务逻辑自行实现 } return user; } }