增加扫码登录功能

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.setUrl(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;
}

View File

@ -5,7 +5,10 @@ import com.alibaba.fastjson2.JSONObject;
import com.google.gson.reflect.TypeToken;
import com.mdd.common.config.GlobalConfig;
import java.io.*;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
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>
*

View File

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

View File

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

View File

@ -83,11 +83,11 @@ public interface ILoginService {
* @param session session
* @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 unionId = uniId == null ? "0" : uniId;
UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
.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());
return this.userService(openId, unionId, client);
} catch (WxErrorException e) {
throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
}
@ -250,81 +193,7 @@ public class LoginServiceImpl implements ILoginService {
String uniId = wxOAuth2AccessToken.getUnionId();
String openId = wxOAuth2AccessToken.getOpenId();
String unionId = uniId == null ? "0" : uniId;
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());
return this.userService(openId, unionId, client);
} catch (WxErrorException e) {
throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
}
@ -394,7 +263,7 @@ public class LoginServiceImpl implements ILoginService {
* @return String
*/
@Override
public String getScanCode(HttpSession session) {
public String getScanCode(String url, HttpSession session) {
// 获取AppId
String appId = ConfigUtils.get("op_channel", "appId", "");
@ -408,7 +277,7 @@ public class LoginServiceImpl implements ILoginService {
"#wechat_redirect";
// 回调地址
String redirectUrl = "https://www.baidu.com/";
String redirectUrl = url;
try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
@ -418,7 +287,6 @@ public class LoginServiceImpl implements ILoginService {
// 防止csrf攻击
String state = ToolsUtils.makeUUID().replaceAll("-", "");
RedisUtils.set("wechat-open-state-"+session.getId(), state, 600);
//生成qrcodeUrl
return String.format(baseUrl, appId, redirectUrl, state);
}
@ -430,7 +298,7 @@ public class LoginServiceImpl implements ILoginService {
* @param scanLoginValidate 参数
*/
@Override
public void scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session) {
public LoginTokenVo scanLogin(ScanLoginValidate scanLoginValidate, HttpSession session) {
Object o = RedisUtils.get("wechat-open-state-"+session.getId());
if (StringUtils.isNull(o) || !o.toString().equals(scanLoginValidate.getState())) {
throw new OperateException("二维码已失效或不存在,请重新操作");
@ -448,26 +316,33 @@ public class LoginServiceImpl implements ILoginService {
"&code=%s" +
"&grant_type=authorization_code";
String result = null;
Map<String, String> resultMap;
try {
String accessTokenUrl = String.format(baseAccessTokenUrl, appId, appSecret, code);
result = HttpUtils.sendGet(accessTokenUrl);
String result = HttpUtils.sendGet(accessTokenUrl);
resultMap = ToolsUtils.jsonToMap(result);
} catch (Exception e) {
throw new OperateException("获取access_token失败:"+e.getMessage());
}
String accessToken = "";
String openid = "";
// 访问微信获取用户信息
// 访问微信获取用户信息 (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);
String resultUserInfo = null;
Map<String, String> userinfoMap;
try {
resultUserInfo = HttpUtils.sendGet(userInfoUrl);
String resultUserInfo = HttpUtils.sendGet(userInfoUrl);
userinfoMap = ToolsUtils.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;
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;
}
/**
* 用户创建服务
*
* @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 Integer genType;
private String genPath;
private Integer menuStatus;
private Integer menuPid;
private String menuName;
private String remarks;
private Long createTime;
private Long updateTime;