登录与注册

This commit is contained in:
TinyAnts 2022-09-05 16:49:04 +08:00
parent 1768127ea0
commit 006978a484
10 changed files with 460 additions and 5 deletions

View File

@ -145,6 +145,12 @@
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
</dependency>
<!-- 微信小程序 -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.4.0</version>
</dependency>
</dependencies>
</project>

View File

@ -16,13 +16,14 @@ public class User implements Serializable {
@TableId(value="id", type= IdType.AUTO)
private Integer id; // 主键
private String sn; // 编号
private Integer sn; // 编号
private String avatar; // 用户头像
private String realName; // 真实姓名
private String nickname; // 用户昵称
private String username; // 用户账号
private String password; // 用户密码
private String mobile; // 用户电话
private Integer channel; // 注册渠道
private String salt; // 加密盐巴
private Integer sex; // 用户性别: [1=, 2=]
private Integer is_delete; // 是否删除: [0=, 1=]

View File

@ -0,0 +1,26 @@
package com.mdd.common.entity.user;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
/**
* 用户授权实体
*/
@Data
public class UserAuth implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value="id", type= IdType.AUTO)
private Integer id; // 主键
private Integer userId; // 用户Id
private String openid; // Openid
private String unionid; // Unionid
private Integer client; // 客户端类型: [1=微信小程序, 2=微信公众号, 3=手机H54=电脑PC, 5=苹果APP, 6=安卓APP]
private Long createTime; // 创建时间
private Long updateTime; // 更新时间
}

View File

@ -0,0 +1,79 @@
package com.mdd.common.enums;
/**
* 客户端枚举类
*/
public enum ClientEnum {
MNP(1, "微信小程序"),
OA(2, "微信公众号"),
H5(3, "手机H5"),
PC(4, "电脑PC"),
IOS(5, "苹果APP"),
APK(5, "安卓APP");
/**
* 构造方法
*/
private final int code;
private final String msg;
ClientEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* 根据类型获取Code
*
* @author fzr
* @param type 类型
* @return Integer
*/
public static Integer getCodeByType(String type){
for(ClientEnum enumItem: ClientEnum.values()) {
if (enumItem.toString().equals(type.toUpperCase())) {
return enumItem.getCode();
}
}
return null;
}
/**
* 根据类型获取Msg
*
* @author fzr
* @param type 类型
* @return String
*/
public static String getMsgByType(String type){
for(ClientEnum enumItem: ClientEnum.values()) {
if (enumItem.toString().equals(type)) {
return enumItem.getMsg();
}
}
return null;
}
/**
* 获取状态码
*
* @author fzr
* @return Long
*/
public int getCode() {
return this.code;
}
/**
* 获取提示
*
* @author fzr
* @return String
*/
public String getMsg() {
return this.msg;
}
}

View File

@ -0,0 +1,12 @@
package com.mdd.common.mapper.user;
import com.mdd.common.core.basics.IBaseMapper;
import com.mdd.common.entity.user.UserAuth;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户授权Mapper
*/
@Mapper
public interface UserAuthMapper extends IBaseMapper<UserAuth> {
}

View File

@ -1,4 +0,0 @@
package com.mdd.common.plugin.wechat;
public class WechatDriver {
}

View File

@ -0,0 +1,56 @@
package com.mdd.front.controller;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.enums.ClientEnum;
import com.mdd.front.service.ILoginService;
import com.mdd.front.validate.RegisterParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/login")
public class LoginController {
@Resource
ILoginService iLoginService;
/**
* 注册账号
*
* @author fzr
* @param registerParam 参数
* @return Object
*/
@PostMapping("/register")
public Object register(@Validated @RequestBody RegisterParam registerParam) {
iLoginService.register(registerParam);
return AjaxResult.success();
}
@PostMapping("/check")
public Object check(@RequestBody Map<String, String> params) {
Assert.notNull(params.get("scene"), "scene参数缺失!");
Map<String, Object> map = new LinkedHashMap<>();
switch (params.get("scene")) {
case "mnp":
map = iLoginService.mnpLogin(params);
break;
case "sms":
Assert.isNull(params.get("code"), "code参数缺失!");
iLoginService.smsLogin(params);
break;
case "account":
iLoginService.accountLogin(params);
break;
}
return AjaxResult.success(map);
}
}

View File

@ -0,0 +1,34 @@
package com.mdd.front.service;
import com.mdd.front.validate.RegisterParam;
import java.util.Map;
/**
* 登录服务接口类
*/
public interface ILoginService {
/**
* 账号注册
*
* @author fzr
* @param registerParam 参数
*/
void register(RegisterParam registerParam);
/**
* 微信小程序登录
*
* @author fzr
* @param scene 场景
* @param code 编码
*/
Map<String, Object> mnpLogin(Map<String, String> params);
void smsLogin(Map<String, String> params);
void accountLogin(Map<String, String> params);
void forgotPassword(Map<String, String> params);
}

View File

@ -0,0 +1,210 @@
package com.mdd.front.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.mdd.common.entity.user.User;
import com.mdd.common.entity.user.UserAuth;
import com.mdd.common.enums.ClientEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.user.UserAuthMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.utils.ConfigUtil;
import com.mdd.common.utils.IpUtil;
import com.mdd.common.utils.StringUtil;
import com.mdd.common.utils.ToolsUtil;
import com.mdd.front.service.ILoginService;
import com.mdd.front.validate.RegisterParam;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 登录服务实现类
*/
@Service
public class LoginServiceImpl implements ILoginService {
@Resource
UserMapper userMapper;
@Resource
UserAuthMapper userAuthMapper;
/**
* 注册账号
*
* @author fzr
* @param registerParam 参数
*/
@Override
public void register(RegisterParam registerParam) {
User model = userMapper.selectOne(new QueryWrapper<User>()
.select("id,sn,username")
.eq("username", registerParam.getUsername())
.eq("is_delete", 0)
.last("limit 1"));
Assert.isNull(model, "账号已存在,换一个吧!");
Integer sn = this.randMakeSn();
String salt = ToolsUtil.randomString(5);
String pwd = ToolsUtil.makeMd5(registerParam.getPassword()+salt);
User user = new User();
user.setSn(sn);
user.setNickname("用户"+sn);
user.setUsername(registerParam.getUsername());
user.setPassword(pwd);
user.setSalt(salt);
user.setChannel(0);
user.setCreateTime(System.currentTimeMillis() / 1000);
user.setUpdateTime(System.currentTimeMillis() / 1000);
userMapper.insert(user);
}
/**
* 微信小程序登录
*
* @author fzr
* @param params 参数
* @return Map<String, Object>
*/
@Override
@Transactional
public Map<String, Object> mnpLogin(Map<String, String> params) {
Assert.notNull(params.get("code"), "code参数缺失!");
String scene = params.get("scene");
String code = params.get("code");
String avatarUrl = params.getOrDefault("avatarUrl", "");
String nickName = params.getOrDefault("nickName", "");
String gender = params.getOrDefault("gender", "0");
Integer client = ClientEnum.getCodeByType(scene);
Map<String, String> config = ConfigUtil.get("mp_channel");
WxMaService wxMaService = new WxMaServiceImpl();
WxMaDefaultConfigImpl wxConfig = new WxMaDefaultConfigImpl();
wxConfig.setAppid(config.getOrDefault("appId", ""));
wxConfig.setSecret(config.getOrDefault("appSecret", ""));
wxMaService.setWxMaConfig(wxConfig);
try {
WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
String openId = sessionResult.getOpenid();
String unionId = sessionResult.getUnionid();
UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.eq("client", client)
.nested(wq->wq
.eq("openid", openId).or()
.eq("unionid", unionId)
).last("limit 1"));
User user = null;
Integer userId;
if (StringUtil.isNotNull(userAuth)) {
user = userMapper.selectOne(new QueryWrapper<User>()
.eq("id", userAuth.getUserId())
.eq("is_delete", 0)
.last("limit 1"));
}
if (StringUtil.isNull(user)) {
Integer sn = this.randMakeSn();
User model = new User();
model.setSn(sn);
model.setAvatar(avatarUrl);
model.setNickname(nickName.equals("")?"用户"+sn:nickName);
model.setUsername("u"+sn);
model.setSex(Integer.parseInt(gender));
model.setChannel(client);
model.setLastLoginIp(IpUtil.getHostIp());
model.setLastLoginTime(System.currentTimeMillis() / 1000);
model.setCreateTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000);
userMapper.insert(model);
userId = model.getId();
UserAuth auth = new UserAuth();
auth.setUserId(model.getId());
auth.setOpenid(openId);
auth.setUnionid(unionId);
auth.setClient(client);
auth.setCreateTime(System.currentTimeMillis() / 1000);
auth.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(auth);
} else {
// 更新微信标识
userId = user.getId();
if (StringUtil.isEmpty(userAuth.getUnionid()) && StringUtil.isNotEmpty(sessionResult.getUnionid())) {
userAuth.setUnionid(sessionResult.getUnionid());
userAuthMapper.updateById(userAuth);
}
// 更新用户信息
if (StringUtil.isEmpty(user.getAvatar()) && StringUtil.isNotEmpty(avatarUrl)) {
user.setAvatar(avatarUrl);
user.setNickname(nickName);
user.setSex(Integer.parseInt(gender));
}
// 更新登录信息
user.setLastLoginIp(IpUtil.getHostIp());
user.setLastLoginTime(System.currentTimeMillis() / 1000);
userMapper.updateById(user);
}
String token = ToolsUtil.makeToken();
Map<String, Object> response = new LinkedHashMap<>();
response.put("id", userId);
response.put("token", token);
return response;
} catch (WxErrorException e) {
throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
}
}
@Override
public void smsLogin(Map<String, String> params) {
}
@Override
public void accountLogin(Map<String, String> params) {
}
@Override
public void forgotPassword(Map<String, String> params) {
}
/**
* 生成用户编号
*
* @author fzr
* @return Integer
*/
private Integer randMakeSn() {
Integer sn;
while (true) {
sn = Integer.parseInt(ToolsUtil.randomInt(8));
User snModel = userMapper.selectOne(new QueryWrapper<User>()
.select("id,sn,username")
.eq("sn", sn)
.last("limit 1"));
if (snModel == null) {
break;
}
}
return sn;
}
}

View File

@ -0,0 +1,35 @@
package com.mdd.front.validate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
* 注册参数类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class RegisterParam implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "username参数缺失")
@NotEmpty(message = "账号不能为空")
@Length(min = 3, max = 12, message = "账号必须在3~12个字符内")
@Pattern(message = "账号只允许是字母和数字", regexp="^[A-Za-z0-9]+$")
@Pattern(message = "账号应该为3-12位字母、数字组合", regexp="^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{3,12}$")
private String username;
@NotNull(message = "password参数缺失")
@NotEmpty(message = "密码不能为空")
@Length(min = 6, max = 12, message = "密码必须在6~12个字符内")
private String password;
}