增加扫码登录功能

This commit is contained in:
TinyAnts 2023-01-06 16:13:46 +08:00
parent f2450bc615
commit 853e64fee5
7 changed files with 148 additions and 159 deletions

View File

@ -82,14 +82,6 @@ public class StorageDriver {
vo.setExt(origFileExt.toLowerCase()); vo.setExt(origFileExt.toLowerCase());
vo.setUrl(newFileName); vo.setUrl(newFileName);
vo.setPath(UrlUtils.toAbsoluteUrl(newFileName)); vo.setPath(UrlUtils.toAbsoluteUrl(newFileName));
// Map<String, Object> map = new LinkedHashMap<>();
// map.put("id", 0);
// map.put("name", multipartFile.getOriginalFilename());
// map.put("size", multipartFile.getSize());
// map.put("ext", origFileExt.toLowerCase());
// map.put("url", newFileName);
// map.put("path", UrlUtil.toAbsoluteUrl(newFileName));
return vo; return vo;
} }

View File

@ -5,7 +5,10 @@ import com.alibaba.fastjson2.JSONObject;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.mdd.common.config.GlobalConfig; import com.mdd.common.config.GlobalConfig;
import java.io.*;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.*; import java.util.*;
@ -127,6 +130,37 @@ public class ToolsUtils {
} }
} }
/**
* 下载文件
*
* @author fzr
* @param urlString (文件网址)
* @param savePath (保存路径,: /www/uploads)
* @param filename (保存名称,: aa.png)
* @throws IOException 异常
*/
public static void download(String urlString, String savePath, String filename) throws IOException {
URL url = new URL(urlString);
URLConnection con = url.openConnection();
con.setConnectTimeout(20 * 1000);
File sf = new File(savePath);
if (!sf.exists()) {
if (sf.mkdirs()) {
throw new IOException("创建目录失败");
}
}
try (InputStream in = con.getInputStream();
OutputStream out = new FileOutputStream(sf.getPath() + "\\" + filename)) {
byte[] buff = new byte[1024];
int n;
while ((n = in.read(buff)) >= 0) {
out.write(buff, 0, n);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** /**
* JSON转 Map<String, String> * JSON转 Map<String, String>
* *

View File

@ -31,6 +31,7 @@ public class FrontConfig {
"/api/pc/getConfig", "/api/pc/getConfig",
"/api/pc/index", "/api/pc/index",
"/api/login/getScanCode", "/api/login/getScanCode",
"/api/login/scanLogin",
}; };

View File

@ -129,8 +129,8 @@ public class LoginController {
* @return AjaxResult<LoginUrlsVo> * @return AjaxResult<LoginUrlsVo>
*/ */
@GetMapping("/getScanCode") @GetMapping("/getScanCode")
public AjaxResult<LoginUrlsVo> getScanCode(HttpSession session) { public AjaxResult<LoginUrlsVo> getScanCode(@RequestParam String url, HttpSession session) {
String qrcodeUrl = iLoginService.getScanCode(session); String qrcodeUrl = iLoginService.getScanCode(url, session);
LoginUrlsVo vo = new LoginUrlsVo(); LoginUrlsVo vo = new LoginUrlsVo();
vo.setUrl(qrcodeUrl); vo.setUrl(qrcodeUrl);
return AjaxResult.success(vo); return AjaxResult.success(vo);
@ -145,8 +145,8 @@ public class LoginController {
*/ */
@PostMapping("/scanLogin") @PostMapping("/scanLogin")
public AjaxResult<Object> scanLogin(@Validated @RequestBody ScanLoginValidate scanLoginValidate, HttpSession session) { public AjaxResult<Object> scanLogin(@Validated @RequestBody ScanLoginValidate scanLoginValidate, HttpSession session) {
iLoginService.scanLogin(scanLoginValidate, session); LoginTokenVo vo = iLoginService.scanLogin(scanLoginValidate, session);
return AjaxResult.success(); return AjaxResult.success(vo);
} }
} }

View File

@ -83,11 +83,11 @@ public interface ILoginService {
* @param session session * @param session session
* @return String * @return String
*/ */
String getScanCode(HttpSession session); String getScanCode(String url, HttpSession session);
/** /**
* 扫码登录 * 扫码登录
*/ */
void scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session); LoginTokenVo scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session);
} }

View File

@ -173,64 +173,7 @@ public class LoginServiceImpl implements ILoginService {
String uniId = sessionResult.getUnionid(); String uniId = sessionResult.getUnionid();
String unionId = uniId == null ? "0" : uniId; String unionId = uniId == null ? "0" : uniId;
UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>() return this.userService(openId, unionId, client);
.nested(wq->wq
.eq("openid", openId).or()
.eq("unionid", unionId)
).last("limit 1"));
User user = null;
Integer userId;
if (StringUtils.isNotNull(userAuth)) {
user = userMapper.selectOne(new QueryWrapper<User>()
.eq("id", userAuth.getUserId())
.eq("is_delete", 0)
.last("limit 1"));
}
if (StringUtils.isNull(user)) {
Integer sn = this.randMakeSn();
User model = new User();
model.setSn(sn);
model.setAvatar("/api/static/default_avatar.png");
model.setNickname("用户"+sn);
model.setUsername("u"+sn);
model.setSex(0);
model.setChannel(client);
model.setLastLoginIp(IpUtils.getHostIp());
model.setLastLoginTime(System.currentTimeMillis() / 1000);
model.setCreateTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000);
userMapper.insert(model);
user = model;
userId = model.getId();
if (StringUtils.isNull(userAuth)) {
UserAuth auth = new UserAuth();
auth.setUserId(model.getId());
auth.setOpenid(openId);
auth.setUnionid(unionId.equals("0") ? "" : unionId);
auth.setClient(client);
auth.setCreateTime(System.currentTimeMillis() / 1000);
auth.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(auth);
}
} else {
// 更新微信标识
userId = user.getId();
if (StringUtils.isEmpty(userAuth.getUnionid()) && StringUtils.isNotEmpty(sessionResult.getUnionid())) {
userAuth.setUnionid(sessionResult.getUnionid());
userAuthMapper.updateById(userAuth);
}
// 更新登录信息
user.setLastLoginIp(IpUtils.getHostIp());
user.setLastLoginTime(System.currentTimeMillis() / 1000);
userMapper.updateById(user);
}
return this.makeLoginToken(userId, user.getMobile());
} catch (WxErrorException e) { } catch (WxErrorException e) {
throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg()); throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
} }
@ -250,81 +193,7 @@ public class LoginServiceImpl implements ILoginService {
String uniId = wxOAuth2AccessToken.getUnionId(); String uniId = wxOAuth2AccessToken.getUnionId();
String openId = wxOAuth2AccessToken.getOpenId(); String openId = wxOAuth2AccessToken.getOpenId();
String unionId = uniId == null ? "0" : uniId; String unionId = uniId == null ? "0" : uniId;
return this.userService(openId, unionId, client);
UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.nested(wq->wq
.eq("unionid", unionId).or()
.eq("openid", openId)
).last("limit 1"));
Integer userId;
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.randMakeSn();
User model = new User();
model.setSn(sn);
model.setAvatar("/api/static/default_avatar.png");
model.setNickname("用户" + sn);
model.setUsername("u" + sn);
model.setChannel(client);
model.setSex(0);
model.setLastLoginIp(IpUtils.getHostIp());
model.setLastLoginTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setCreateTime(System.currentTimeMillis() / 1000);
userMapper.insert(model);
userId = model.getId();
user = model;
if (StringUtils.isNull(userAuth)) {
UserAuth auth = new UserAuth();
auth.setUserId(model.getId());
auth.setUnionid(unionId);
auth.setOpenid(openId);
auth.setClient(client);
auth.setCreateTime(System.currentTimeMillis() / 1000);
auth.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(auth);
}
} else {
userId = user.getId();
// 授权不存在则创建
UserAuth auth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.nested(wq->wq
.eq("unionid", unionId).or()
.eq("openid", openId)
).eq("client", client)
.last("limit 1"));
if (StringUtils.isNull(auth)) {
UserAuth authModel = new UserAuth();
authModel.setUserId(user.getId());
authModel.setUnionid(unionId);
authModel.setOpenid(openId);
authModel.setClient(client);
authModel.setCreateTime(System.currentTimeMillis() / 1000);
authModel.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(authModel);
} else if(StringUtils.isEmpty(auth.getUnionid()) && StringUtils.isNotEmpty(unionId)) {
auth.setUnionid(unionId);
userAuthMapper.updateById(userAuth);
}
// 更新登录信息
user.setLastLoginIp(IpUtils.getHostIp());
user.setLastLoginTime(System.currentTimeMillis() / 1000);
userMapper.updateById(user);
}
return this.makeLoginToken(userId, user.getMobile());
} catch (WxErrorException e) { } catch (WxErrorException e) {
throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg()); throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
} }
@ -394,7 +263,7 @@ public class LoginServiceImpl implements ILoginService {
* @return String * @return String
*/ */
@Override @Override
public String getScanCode(HttpSession session) { public String getScanCode(String url, HttpSession session) {
// 获取AppId // 获取AppId
String appId = ConfigUtils.get("op_channel", "appId", ""); String appId = ConfigUtils.get("op_channel", "appId", "");
@ -408,7 +277,7 @@ public class LoginServiceImpl implements ILoginService {
"#wechat_redirect"; "#wechat_redirect";
// 回调地址 // 回调地址
String redirectUrl = "https://www.baidu.com/"; String redirectUrl = url;
try { try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8"); redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -418,7 +287,6 @@ public class LoginServiceImpl implements ILoginService {
// 防止csrf攻击 // 防止csrf攻击
String state = ToolsUtils.makeUUID().replaceAll("-", ""); String state = ToolsUtils.makeUUID().replaceAll("-", "");
RedisUtils.set("wechat-open-state-"+session.getId(), state, 600); RedisUtils.set("wechat-open-state-"+session.getId(), state, 600);
//生成qrcodeUrl //生成qrcodeUrl
return String.format(baseUrl, appId, redirectUrl, state); return String.format(baseUrl, appId, redirectUrl, state);
} }
@ -430,7 +298,7 @@ public class LoginServiceImpl implements ILoginService {
* @param scanLoginValidate 参数 * @param scanLoginValidate 参数
*/ */
@Override @Override
public void scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session) { public LoginTokenVo scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session) {
Object o = RedisUtils.get("wechat-open-state-"+session.getId()); Object o = RedisUtils.get("wechat-open-state-"+session.getId());
if (StringUtils.isNull(o) || !o.toString().equals(scanLoginValidate.getState())) { if (StringUtils.isNull(o) || !o.toString().equals(scanLoginValidate.getState())) {
throw new OperateException("二维码已失效或不存在,请重新操作"); throw new OperateException("二维码已失效或不存在,请重新操作");
@ -448,26 +316,33 @@ public class LoginServiceImpl implements ILoginService {
"&code=%s" + "&code=%s" +
"&grant_type=authorization_code"; "&grant_type=authorization_code";
String result = null; Map<String, String> resultMap;
try { try {
String accessTokenUrl = String.format(baseAccessTokenUrl, appId, appSecret, code); String accessTokenUrl = String.format(baseAccessTokenUrl, appId, appSecret, code);
result = HttpUtils.sendGet(accessTokenUrl); String result = HttpUtils.sendGet(accessTokenUrl);
resultMap = ToolsUtils.jsonToMap(result);
} catch (Exception e) { } catch (Exception e) {
throw new OperateException("获取access_token失败:"+e.getMessage()); throw new OperateException("获取access_token失败:"+e.getMessage());
} }
String accessToken = ""; // 访问微信获取用户信息 (openId,unionId,昵称,头像等)
String openid = ""; 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 baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid); String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
String resultUserInfo = null; Map<String, String> userinfoMap;
try { try {
resultUserInfo = HttpUtils.sendGet(userInfoUrl); String resultUserInfo = HttpUtils.sendGet(userInfoUrl);
userinfoMap = ToolsUtils.jsonToMap(resultUserInfo);
} catch (Exception e) { } catch (Exception e) {
throw new OperateException("获取用户信息失败:"+e.getMessage()); throw new OperateException("获取用户信息失败:"+e.getMessage());
} }
String openId = userinfoMap.get("openid");
String uniId = userinfoMap.get("unionid");
String unionId = uniId == null ? "0" : uniId;
RedisUtils.del("wechat-open-state-"+session.getId());
return this.userService(openId, unionId, ClientEnum.PC.getCode());
} }
/** /**
@ -490,6 +365,90 @@ public class LoginServiceImpl implements ILoginService {
return vo; return vo;
} }
/**
* 用户创建服务
*
* @param openId (openId)
* @param unionId (unionId)
* @param client (client)
* @return LoginTokenVo
*/
private LoginTokenVo userService(String openId, String unionId, Integer client) {
UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.nested(wq->wq
.eq("unionid", unionId).or()
.eq("openid", openId)
).last("limit 1"));
Integer userId;
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.randMakeSn();
User model = new User();
model.setSn(sn);
model.setAvatar("/api/static/default_avatar.png");
model.setNickname("用户" + sn);
model.setUsername("u" + sn);
model.setChannel(ClientEnum.PC.getCode());
model.setSex(0);
model.setLastLoginIp(IpUtils.getHostIp());
model.setLastLoginTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setCreateTime(System.currentTimeMillis() / 1000);
userMapper.insert(model);
userId = model.getId();
user = model;
if (StringUtils.isNull(userAuth)) {
UserAuth auth = new UserAuth();
auth.setUserId(model.getId());
auth.setUnionid(unionId);
auth.setOpenid(openId);
auth.setClient(client);
auth.setCreateTime(System.currentTimeMillis() / 1000);
auth.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(auth);
}
} else {
// 授权不存在则创建
userId = user.getId();
UserAuth auth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.nested(wq->wq
.eq("unionid", unionId).or()
.eq("openid", openId)
).eq("client", client)
.last("limit 1"));
if (StringUtils.isNull(auth)) {
UserAuth authModel = new UserAuth();
authModel.setUserId(user.getId());
authModel.setUnionid(unionId);
authModel.setOpenid(openId);
authModel.setClient(client);
authModel.setCreateTime(System.currentTimeMillis() / 1000);
authModel.setUpdateTime(System.currentTimeMillis() / 1000);
userAuthMapper.insert(authModel);
} else if(StringUtils.isEmpty(auth.getUnionid()) && StringUtils.isNotEmpty(unionId)) {
auth.setUnionid(unionId);
userAuthMapper.updateById(userAuth);
}
// 更新登录信息
user.setLastLoginIp(IpUtils.getHostIp());
user.setLastLoginTime(System.currentTimeMillis() / 1000);
userMapper.updateById(user);
}
return this.makeLoginToken(userId, user.getMobile());
}
/** /**
* 生成用户编号 * 生成用户编号
* *

View File

@ -31,6 +31,9 @@ public class GenTable implements Serializable {
private String genTpl; private String genTpl;
private Integer genType; private Integer genType;
private String genPath; private String genPath;
private Integer menuStatus;
private Integer menuPid;
private String menuName;
private String remarks; private String remarks;
private Long createTime; private Long createTime;
private Long updateTime; private Long updateTime;