|
@@ -1,445 +0,0 @@
|
|
|
-package com.sckj.front.service.impl;
|
|
|
-
|
|
|
-import cn.binarywang.wx.miniapp.api.WxMaService;
|
|
|
-import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
|
|
-import cn.dev33.satoken.stp.StpUtil;
|
|
|
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
-import com.baomidou.mybatisplus.core.toolkit.Assert;
|
|
|
-import com.sckj.common.entity.user.User;
|
|
|
-import com.sckj.common.entity.user.UserAuth;
|
|
|
-import com.sckj.common.enums.NoticeEnum;
|
|
|
-import com.sckj.common.exception.OperateException;
|
|
|
-import com.sckj.common.mapper.user.UserAuthMapper;
|
|
|
-import com.sckj.common.mapper.user.UserMapper;
|
|
|
-import com.sckj.common.plugin.notice.NoticeCheck;
|
|
|
-import com.sckj.common.plugin.wechat.WxMnpDriver;
|
|
|
-import com.sckj.common.util.*;
|
|
|
-import com.sckj.front.cache.ScanLoginCache;
|
|
|
-import com.sckj.front.service.ILoginService;
|
|
|
-import com.sckj.front.vo.login.LoginTokenVo;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import me.chanjar.weixin.common.api.WxConsts;
|
|
|
-import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
|
|
|
-import me.chanjar.weixin.common.error.WxErrorException;
|
|
|
-import me.chanjar.weixin.mp.api.WxMpService;
|
|
|
-import me.chanjar.weixin.mp.api.impl.WxMpOAuth2ServiceImpl;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
-
|
|
|
-import javax.annotation.Resource;
|
|
|
-import javax.servlet.http.HttpSession;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.UnsupportedEncodingException;
|
|
|
-import java.net.URLEncoder;
|
|
|
-import java.util.Map;
|
|
|
-
|
|
|
-/**
|
|
|
- * 登录服务实现类
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-@Service
|
|
|
-public class LoginServiceImpl implements ILoginService {
|
|
|
-
|
|
|
- @Resource
|
|
|
- UserMapper userMapper;
|
|
|
-
|
|
|
- @Resource
|
|
|
- UserAuthMapper userAuthMapper;
|
|
|
-
|
|
|
- /**
|
|
|
- * 注册账号
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param username 账号
|
|
|
- * @param password 密码
|
|
|
- * @param terminal 总端
|
|
|
- */
|
|
|
- @Override
|
|
|
- public void register(String username, String password, Integer terminal) {
|
|
|
- User model = userMapper.selectOne(new QueryWrapper<User>()
|
|
|
- .select("id,sn,username")
|
|
|
- .eq("username", username)
|
|
|
- .eq("is_delete", 0)
|
|
|
- .last("limit 1"));
|
|
|
-
|
|
|
- Assert.isNull(model, "账号已存在,换一个吧!");
|
|
|
-
|
|
|
- Integer sn = this.__generateSn();
|
|
|
- String salt = ToolUtils.randomString(5);
|
|
|
- String pwd = ToolUtils.makeMd5(password+salt);
|
|
|
-
|
|
|
- User user = new User();
|
|
|
- user.setSn(sn);
|
|
|
- user.setNickname("用户"+sn);
|
|
|
- user.setUsername(username);
|
|
|
- user.setPassword(pwd);
|
|
|
- user.setSalt(salt);
|
|
|
- user.setAvatar("/api/static/default_avatar.png");
|
|
|
- user.setChannel(terminal);
|
|
|
- user.setIsNew(1);
|
|
|
- user.setCreateTime(System.currentTimeMillis() / 1000);
|
|
|
- user.setUpdateTime(System.currentTimeMillis() / 1000);
|
|
|
- userMapper.insert(user);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 账号登录
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param username 账号
|
|
|
- * @param password 密码
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- @Override
|
|
|
- public LoginTokenVo accountLogin(String username, String password, Integer terminal) {
|
|
|
- User user = userMapper.selectOne(new QueryWrapper<User>()
|
|
|
- .select("id,username,password,salt,mobile,is_disable,is_new")
|
|
|
- .eq("username", username)
|
|
|
- .eq("is_delete", 0)
|
|
|
- .last("limit 1"));
|
|
|
-
|
|
|
- Assert.notNull(user, "账号不存在!");
|
|
|
- String pwd = ToolUtils.makeMd5(password+user.getSalt());
|
|
|
- Assert.isFalse(!pwd.equals(user.getPassword()), "账号或密码错误!");
|
|
|
- Assert.isFalse(!user.getIsDisable().equals(0), "账号已被禁用!");
|
|
|
-
|
|
|
- return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 手机号登录
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param mobile 手机号
|
|
|
- * @param code 验证码
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- @Override
|
|
|
- public LoginTokenVo mobileLogin(String mobile, String code, Integer terminal) {
|
|
|
- // 校验验证码
|
|
|
- int sceneCode = NoticeEnum.LOGIN_CODE.getCode();
|
|
|
- if (!NoticeCheck.verify(sceneCode, code)) {
|
|
|
- throw new OperateException("验证码错误!");
|
|
|
- }
|
|
|
-
|
|
|
- // 查询手机号
|
|
|
- User user = userMapper.selectOne(new QueryWrapper<User>()
|
|
|
- .select("id,username,mobile,is_disable,is_new")
|
|
|
- .eq("mobile", mobile)
|
|
|
- .eq("is_delete", 0)
|
|
|
- .last("limit 1"));
|
|
|
-
|
|
|
- Assert.notNull(user, "账号不存在!");
|
|
|
- Assert.isFalse(user.getIsDisable() != 0, "账号已禁用!");
|
|
|
-
|
|
|
- return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 微信小程序登录
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param code 编码
|
|
|
- * @param terminal 终端
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- @Override
|
|
|
- @Transactional
|
|
|
- public LoginTokenVo mnpLogin(String code, Integer terminal) {
|
|
|
- try {
|
|
|
- WxMaService wxMaService = WxMnpDriver.mnp();
|
|
|
- WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
|
|
|
- String openId = sessionResult.getOpenid();
|
|
|
- String uniId = sessionResult.getUnionid();
|
|
|
- String unionId = uniId == null ? "0" : uniId;
|
|
|
-
|
|
|
- return this.__wxLoginHandle(openId, unionId, "", "", terminal);
|
|
|
- } catch (WxErrorException e) {
|
|
|
- throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 公众号登录
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param code 编码
|
|
|
- * @param terminal 终端
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- @Override
|
|
|
- public LoginTokenVo officeLogin(String code, Integer terminal) {
|
|
|
- try {
|
|
|
- WxMpService wxMpService = WxMnpDriver.oa();
|
|
|
- WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
|
|
|
- String uniId = wxOAuth2AccessToken.getUnionId();
|
|
|
- String openId = wxOAuth2AccessToken.getOpenId();
|
|
|
- String unionId = uniId == null ? "0" : uniId;
|
|
|
-
|
|
|
- String avatar = "";
|
|
|
- String nickname = "";
|
|
|
- try {
|
|
|
- String accessToken = wxOAuth2AccessToken.getAccessToken();
|
|
|
- String userInfoUri = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
|
|
|
- String userInfoUrl = String.format(userInfoUri, accessToken, openId);
|
|
|
- String resultInfo = HttpUtils.sendGet(userInfoUrl);
|
|
|
- Map<String, String> resultMap = MapUtils.jsonToMap(resultInfo);
|
|
|
- avatar = resultMap.get("headimgurl");
|
|
|
- nickname = resultMap.get("nickname");
|
|
|
- } catch (Exception ignored) {}
|
|
|
-
|
|
|
- return this.__wxLoginHandle(openId, unionId, avatar, nickname, terminal);
|
|
|
- } catch (WxErrorException e) {
|
|
|
- throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 公众号跳转url
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param url 连接
|
|
|
- * @return String
|
|
|
- */
|
|
|
- @Override
|
|
|
- public String oaCodeUrl(String url) {
|
|
|
- WxMpService wxMpService = WxMnpDriver.oa();
|
|
|
- WxMpOAuth2ServiceImpl wxMpOAuth2Service = new WxMpOAuth2ServiceImpl(wxMpService);
|
|
|
- return wxMpOAuth2Service.buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 扫码链接
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param session session
|
|
|
- * @return String
|
|
|
- */
|
|
|
- @Override
|
|
|
- public String scanCodeUrl(String url, HttpSession session) {
|
|
|
- // 获取AppId
|
|
|
- String appId = ConfigUtils.get("op_channel", "appId", "");
|
|
|
-
|
|
|
- // 微信开放平台授权
|
|
|
- String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
|
|
|
- "?appid=%s" +
|
|
|
- "&redirect_uri=%s" +
|
|
|
- "&response_type=code" +
|
|
|
- "&scope=snsapi_login" +
|
|
|
- "&state=%s" +
|
|
|
- "#wechat_redirect";
|
|
|
-
|
|
|
- // 回调地址
|
|
|
- String redirectUrl = url;
|
|
|
- try {
|
|
|
- redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
|
|
|
- } catch (UnsupportedEncodingException e) {
|
|
|
- throw new OperateException(e.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
- // 防止csrf攻击
|
|
|
- String state = ToolUtils.makeUUID().replaceAll("-", "");
|
|
|
- ScanLoginCache.set(session.getId(), state);
|
|
|
-
|
|
|
- //生成QrcodeUrl
|
|
|
- return String.format(baseUrl, appId, redirectUrl, state);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 扫码登录
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param code 编码
|
|
|
- * @param state 标识
|
|
|
- * @param terminal 终端
|
|
|
- * @param session 会话
|
|
|
- */
|
|
|
- @Override
|
|
|
- public LoginTokenVo scanLogin(String code, String state, Integer terminal, HttpSession session) {
|
|
|
- if (!ScanLoginCache.get(session.getId()).equals(state)) {
|
|
|
- throw new OperateException("二维码已失效或不存在,请重新操作");
|
|
|
- }
|
|
|
-
|
|
|
- // 得到配置和授权临时票据code
|
|
|
- String appId = ConfigUtils.get("op_channel", "appId", "");
|
|
|
- String appSecret = ConfigUtils.get("op_channel", "appSecret", "");
|
|
|
-
|
|
|
- //向认证服务器发送请求换取access_token
|
|
|
- String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
|
|
|
- "?appid=%s" +
|
|
|
- "&secret=%s" +
|
|
|
- "&code=%s" +
|
|
|
- "&grant_type=authorization_code";
|
|
|
-
|
|
|
- Map<String, String> resultMap;
|
|
|
- try {
|
|
|
- String accessTokenUrl = String.format(baseAccessTokenUrl, appId, appSecret, code);
|
|
|
- String result = HttpUtils.sendGet(accessTokenUrl);
|
|
|
- resultMap = MapUtils.jsonToMap(result);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new OperateException("获取access_token失败:"+e.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
- // 访问微信获取用户信息 (openId,unionId,昵称,头像等)
|
|
|
- String accessToken = resultMap.get("access_token");
|
|
|
- String openid = resultMap.get("openid");
|
|
|
- String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
|
|
|
- String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
|
|
|
- Map<String, String> userinfoMap;
|
|
|
- try {
|
|
|
- String resultUserInfo = HttpUtils.sendGet(userInfoUrl);
|
|
|
- userinfoMap = MapUtils.jsonToMap(resultUserInfo);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new OperateException("获取用户信息失败:"+e.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
- String openId = userinfoMap.get("openid");
|
|
|
- String uniId = userinfoMap.get("unionid");
|
|
|
- String unionId = uniId == null ? "0" : uniId;
|
|
|
- String avatar = resultMap.getOrDefault("headimgurl", "");
|
|
|
- String nickname = resultMap.getOrDefault("nickname", "");
|
|
|
-
|
|
|
- return this.__wxLoginHandle(openId, unionId, avatar, nickname, terminal);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理微信登录
|
|
|
- *
|
|
|
- * @param openId (openId)
|
|
|
- * @param unionId (unionId)
|
|
|
- * @param terminal (terminal)
|
|
|
- * @param avatar (用户头像)
|
|
|
- * @param nickname (用户昵称)
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- private LoginTokenVo __wxLoginHandle(String openId, String unionId, String avatar, String nickname, Integer terminal) {
|
|
|
- // 查询授权
|
|
|
- UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
|
|
|
- .nested(wq->wq
|
|
|
- .eq("unionid", unionId).or()
|
|
|
- .eq("openid", openId)
|
|
|
- ).last("limit 1"));
|
|
|
-
|
|
|
- // 查询用户
|
|
|
- User user = null;
|
|
|
- if (StringUtils.isNotNull(userAuth)) {
|
|
|
- user = userMapper.selectOne(new QueryWrapper<User>()
|
|
|
- .eq("is_delete", 0)
|
|
|
- .eq("id", userAuth.getUserId())
|
|
|
- .last("limit 1"));
|
|
|
- }
|
|
|
-
|
|
|
- // 创建用户
|
|
|
- if (StringUtils.isNull(user)) {
|
|
|
- Integer sn = this.__generateSn();
|
|
|
- String defaultAvatar = "/api/static/default_avatar.png";
|
|
|
- String defaultNickname = "用户" + sn;
|
|
|
-
|
|
|
- if (StringUtils.isNotEmpty(avatar)) {
|
|
|
- try {
|
|
|
- Long time = System.currentTimeMillis();
|
|
|
- String date = TimeUtils.millisecondToDate(time, "yyyyMMdd");
|
|
|
- String name = ToolUtils.makeMd5(ToolUtils.makeUUID()+time) + ".jpg";
|
|
|
- String path = "avatar" + date + "/" + name;
|
|
|
- String savePath = YmlUtils.get("like.upload-directory") + path;
|
|
|
- ToolUtils.download(avatar, savePath);
|
|
|
- defaultAvatar = path;
|
|
|
- } catch (IOException ignored) {}
|
|
|
- }
|
|
|
-
|
|
|
- if (StringUtils.isNotEmpty(nickname)) {
|
|
|
- defaultNickname = nickname;
|
|
|
- }
|
|
|
-
|
|
|
- User model = new User();
|
|
|
- model.setSn(sn);
|
|
|
- model.setAvatar(defaultAvatar);
|
|
|
- model.setNickname(defaultNickname);
|
|
|
- model.setUsername("u" + sn);
|
|
|
- model.setChannel(terminal);
|
|
|
- model.setSex(0);
|
|
|
- model.setLastLoginIp(IpUtils.getHostIp());
|
|
|
- model.setLastLoginTime(System.currentTimeMillis() / 1000);
|
|
|
- model.setUpdateTime(System.currentTimeMillis() / 1000);
|
|
|
- model.setCreateTime(System.currentTimeMillis() / 1000);
|
|
|
- model.setIsNew(1);
|
|
|
- userMapper.insert(model);
|
|
|
- user = model;
|
|
|
- }
|
|
|
-
|
|
|
- // 终端授权
|
|
|
- UserAuth auth = userAuthMapper.selectOne(
|
|
|
- new QueryWrapper<UserAuth>()
|
|
|
- .eq("openid", openId)
|
|
|
- .eq("terminal", terminal)
|
|
|
- .last("limit 1"));
|
|
|
-
|
|
|
- // 创建授权
|
|
|
- if (StringUtils.isNull(auth)) {
|
|
|
- UserAuth authModel = new UserAuth();
|
|
|
- authModel.setUserId(user.getId());
|
|
|
- authModel.setUnionid(unionId);
|
|
|
- authModel.setOpenid(openId);
|
|
|
- authModel.setTerminal(terminal);
|
|
|
- authModel.setCreateTime(System.currentTimeMillis() / 1000);
|
|
|
- authModel.setUpdateTime(System.currentTimeMillis() / 1000);
|
|
|
- userAuthMapper.insert(authModel);
|
|
|
- } else if (StringUtils.isEmpty(auth.getUnionid())) {
|
|
|
- auth.setUnionid(unionId);
|
|
|
- auth.setUpdateTime(System.currentTimeMillis() / 1000);
|
|
|
- userAuthMapper.updateById(auth);
|
|
|
- }
|
|
|
-
|
|
|
- return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), terminal);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理录令牌
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @param userId 用户ID
|
|
|
- * @param mobile 用户手机
|
|
|
- * @param terminal 终端
|
|
|
- * @return LoginTokenVo
|
|
|
- */
|
|
|
- private LoginTokenVo __loginToken(Integer userId, String mobile, Integer isNew, Integer terminal) {
|
|
|
- // 实现账号登录
|
|
|
- StpUtil.login(userId, String.valueOf(terminal));
|
|
|
-
|
|
|
- // 更新登录信息
|
|
|
- User user = new User();
|
|
|
- user.setLastLoginIp(IpUtils.getHostIp());
|
|
|
- user.setLastLoginTime(System.currentTimeMillis() / 1000);
|
|
|
- userMapper.update(user, new QueryWrapper<User>().eq("id", userId));
|
|
|
-
|
|
|
- // 返回登录信息
|
|
|
- LoginTokenVo vo = new LoginTokenVo();
|
|
|
- vo.setId(userId);
|
|
|
- vo.setIsBindMobile(!StringUtils.isEmpty(mobile));
|
|
|
- vo.setToken(StpUtil.getTokenValue());
|
|
|
- vo.setIsNew(isNew);
|
|
|
- return vo;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 生成用户编号
|
|
|
- *
|
|
|
- * @author fzr
|
|
|
- * @return Integer
|
|
|
- */
|
|
|
- private Integer __generateSn() {
|
|
|
- Integer sn;
|
|
|
- while (true) {
|
|
|
- sn = Integer.parseInt(ToolUtils.randomInt(8));
|
|
|
- User snModel = userMapper.selectOne(new QueryWrapper<User>()
|
|
|
- .select("id,sn")
|
|
|
- .eq("sn", sn)
|
|
|
- .last("limit 1"));
|
|
|
- if (snModel == null) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- return sn;
|
|
|
- }
|
|
|
-
|
|
|
-}
|