mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-13 02:57:13 +08:00
feat: 支持第三方账号登录
Just Auth(开箱即用的整合第三方登录的开源组件,脱离繁琐的第三方登录 SDK,让登录变得 So easy!)
This commit is contained in:
@@ -20,6 +20,8 @@ import java.util.List;
|
||||
|
||||
import top.charles7c.cnadmin.auth.model.vo.RouteVO;
|
||||
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
|
||||
/**
|
||||
* 登录业务接口
|
||||
*
|
||||
@@ -39,6 +41,15 @@ public interface LoginService {
|
||||
*/
|
||||
String login(String username, String password);
|
||||
|
||||
/**
|
||||
* 社交身份登录
|
||||
*
|
||||
* @param authUser
|
||||
* 社交身份信息
|
||||
* @return 令牌
|
||||
*/
|
||||
String socialLogin(AuthUser authUser);
|
||||
|
||||
/**
|
||||
* 构建路由树
|
||||
*
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package top.charles7c.cnadmin.auth.service.impl;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -23,32 +24,38 @@ import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNodeConfig;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
||||
import top.charles7c.cnadmin.auth.model.vo.MetaVO;
|
||||
import top.charles7c.cnadmin.auth.model.vo.RouteVO;
|
||||
import top.charles7c.cnadmin.auth.service.LoginService;
|
||||
import top.charles7c.cnadmin.auth.service.PermissionService;
|
||||
import top.charles7c.cnadmin.common.annotation.TreeField;
|
||||
import top.charles7c.cnadmin.common.constant.RegexConsts;
|
||||
import top.charles7c.cnadmin.common.constant.SysConsts;
|
||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||
import top.charles7c.cnadmin.common.enums.GenderEnum;
|
||||
import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
|
||||
import top.charles7c.cnadmin.common.model.dto.LoginUser;
|
||||
import top.charles7c.cnadmin.common.util.SecureUtils;
|
||||
import top.charles7c.cnadmin.common.util.TreeUtils;
|
||||
import top.charles7c.cnadmin.common.util.helper.LoginHelper;
|
||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||
import top.charles7c.cnadmin.system.model.entity.RoleDO;
|
||||
import top.charles7c.cnadmin.system.model.entity.UserDO;
|
||||
import top.charles7c.cnadmin.system.model.entity.UserSocialDO;
|
||||
import top.charles7c.cnadmin.system.model.vo.DeptDetailVO;
|
||||
import top.charles7c.cnadmin.system.model.vo.MenuVO;
|
||||
import top.charles7c.cnadmin.system.service.DeptService;
|
||||
import top.charles7c.cnadmin.system.service.MenuService;
|
||||
import top.charles7c.cnadmin.system.service.RoleService;
|
||||
import top.charles7c.cnadmin.system.service.UserService;
|
||||
import top.charles7c.cnadmin.system.service.*;
|
||||
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
|
||||
/**
|
||||
* 登录业务实现
|
||||
@@ -65,6 +72,8 @@ public class LoginServiceImpl implements LoginService {
|
||||
private final RoleService roleService;
|
||||
private final MenuService menuService;
|
||||
private final PermissionService permissionService;
|
||||
private final UserRoleService userRoleService;
|
||||
private final UserSocialService userSocialService;
|
||||
|
||||
@Override
|
||||
public String login(String username, String password) {
|
||||
@@ -72,16 +81,44 @@ public class LoginServiceImpl implements LoginService {
|
||||
CheckUtils.throwIfNull(user, "用户名或密码错误");
|
||||
Long userId = user.getId();
|
||||
CheckUtils.throwIfNotEqual(SecureUtils.md5Salt(password, userId.toString()), user.getPassword(), "用户名或密码错误");
|
||||
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, user.getStatus(), "此账号已被禁用,如有疑问,请联系管理员");
|
||||
DeptDetailVO deptDetailVO = deptService.get(user.getDeptId());
|
||||
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, deptDetailVO.getStatus(), "此账号部门已被禁用,如有疑问,请联系管理员");
|
||||
// 登录并缓存用户信息
|
||||
LoginUser loginUser = BeanUtil.copyProperties(user, LoginUser.class);
|
||||
loginUser.setPermissions(permissionService.listPermissionByUserId(userId));
|
||||
loginUser.setRoleCodes(permissionService.listRoleCodeByUserId(userId));
|
||||
loginUser.setRoles(roleService.listByUserId(userId));
|
||||
LoginHelper.login(loginUser);
|
||||
return StpUtil.getTokenValue();
|
||||
this.checkUserStatus(user);
|
||||
return this.login(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String socialLogin(AuthUser authUser) {
|
||||
String source = authUser.getSource();
|
||||
String openId = authUser.getUuid();
|
||||
UserSocialDO userSocial = userSocialService.getBySourceAndOpenId(source, openId);
|
||||
UserDO user;
|
||||
if (null == userSocial) {
|
||||
String username = authUser.getUsername();
|
||||
boolean isMatch = ReUtil.isMatch(RegexConsts.USERNAME, username);
|
||||
UserDO existsUser = userService.getByUsername(username);
|
||||
if (null != existsUser || !isMatch) {
|
||||
username = RandomUtil.randomString(RandomUtil.BASE_CHAR, 5) + IdUtil.fastSimpleUUID();
|
||||
}
|
||||
user = new UserDO();
|
||||
user.setUsername(username);
|
||||
user.setNickname(authUser.getNickname());
|
||||
user.setGender(GenderEnum.valueOf(authUser.getGender().name()));
|
||||
user.setAvatar(authUser.getAvatar());
|
||||
user.setDeptId(SysConsts.SUPER_DEPT_ID);
|
||||
Long userId = userService.save(user);
|
||||
RoleDO role = roleService.getByCode(SysConsts.ADMIN_ROLE_CODE);
|
||||
userRoleService.save(Collections.singletonList(role.getId()), userId);
|
||||
userSocial = new UserSocialDO();
|
||||
userSocial.setUserId(userId);
|
||||
userSocial.setSource(source);
|
||||
userSocial.setOpenId(openId);
|
||||
} else {
|
||||
user = BeanUtil.toBean(userService.get(userSocial.getUserId()), UserDO.class);
|
||||
}
|
||||
this.checkUserStatus(user);
|
||||
userSocial.setMetaJson(JSONUtil.toJsonStr(authUser));
|
||||
userSocial.setLastLoginTime(LocalDateTime.now());
|
||||
userSocialService.saveOrUpdate(userSocial);
|
||||
return this.login(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,4 +157,32 @@ public class LoginServiceImpl implements LoginService {
|
||||
});
|
||||
return BeanUtil.copyToList(treeList, RouteVO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录并缓存用户信息
|
||||
*
|
||||
* @param user
|
||||
* 用户信息
|
||||
* @return 令牌
|
||||
*/
|
||||
private String login(UserDO user) {
|
||||
Long userId = user.getId();
|
||||
LoginUser loginUser = BeanUtil.copyProperties(user, LoginUser.class);
|
||||
loginUser.setPermissions(permissionService.listPermissionByUserId(userId));
|
||||
loginUser.setRoleCodes(permissionService.listRoleCodeByUserId(userId));
|
||||
loginUser.setRoles(roleService.listByUserId(userId));
|
||||
return LoginHelper.login(loginUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户状态
|
||||
*
|
||||
* @param user
|
||||
* 用户信息
|
||||
*/
|
||||
private void checkUserStatus(UserDO user) {
|
||||
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, user.getStatus(), "此账号已被禁用,如有疑问,请联系管理员");
|
||||
DeptDetailVO deptDetailVO = deptService.get(user.getDeptId());
|
||||
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, deptDetailVO.getStatus(), "此账号部门已被禁用,如有疑问,请联系管理员");
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.cnadmin.system.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import top.charles7c.cnadmin.common.base.BaseMapper;
|
||||
import top.charles7c.cnadmin.system.model.entity.UserSocialDO;
|
||||
|
||||
/**
|
||||
* 用户社会化关联 Mapper
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/10/11 22:10
|
||||
*/
|
||||
public interface UserSocialMapper extends BaseMapper<UserSocialDO> {
|
||||
|
||||
/**
|
||||
* 根据来源和开放 ID 查询
|
||||
*
|
||||
* @param source
|
||||
* 来源
|
||||
* @param openId
|
||||
* 开放 ID
|
||||
* @return 用户社会化关联信息
|
||||
*/
|
||||
UserSocialDO selectBySourceAndOpenId(@Param("source") String source, @Param("openId") String openId);
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.cnadmin.system.model.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
/**
|
||||
* 用户社会化关联实体
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/10/11 22:10
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_social")
|
||||
public class UserSocialDO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 来源
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 开放 ID
|
||||
*/
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 附加信息
|
||||
*/
|
||||
private String metaJson;
|
||||
|
||||
/**
|
||||
* 最后登录时间
|
||||
*/
|
||||
private LocalDateTime lastLoginTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
}
|
@@ -22,6 +22,7 @@ import java.util.Set;
|
||||
import top.charles7c.cnadmin.common.base.BaseService;
|
||||
import top.charles7c.cnadmin.common.model.dto.RoleDTO;
|
||||
import top.charles7c.cnadmin.common.model.vo.LabelValueVO;
|
||||
import top.charles7c.cnadmin.system.model.entity.RoleDO;
|
||||
import top.charles7c.cnadmin.system.model.query.RoleQuery;
|
||||
import top.charles7c.cnadmin.system.model.request.RoleRequest;
|
||||
import top.charles7c.cnadmin.system.model.vo.RoleDetailVO;
|
||||
@@ -70,4 +71,13 @@ public interface RoleService extends BaseService<RoleVO, RoleDetailVO, RoleQuery
|
||||
* @return 角色集合
|
||||
*/
|
||||
Set<RoleDTO> listByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色编码查询
|
||||
*
|
||||
* @param code
|
||||
* 角色编码
|
||||
* @return 角色信息
|
||||
*/
|
||||
RoleDO getByCode(String code);
|
||||
}
|
||||
|
@@ -37,6 +37,15 @@ import top.charles7c.cnadmin.system.model.vo.UserVO;
|
||||
*/
|
||||
public interface UserService extends BaseService<UserVO, UserDetailVO, UserQuery, UserRequest> {
|
||||
|
||||
/**
|
||||
* 保存用户信息
|
||||
*
|
||||
* @param user
|
||||
* 用户信息
|
||||
* @return ID
|
||||
*/
|
||||
Long save(UserDO user);
|
||||
|
||||
/**
|
||||
* 上传头像
|
||||
*
|
||||
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.cnadmin.system.service;
|
||||
|
||||
import top.charles7c.cnadmin.system.model.entity.UserSocialDO;
|
||||
|
||||
/**
|
||||
* 用户社会化关联业务接口
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/10/11 22:10
|
||||
*/
|
||||
public interface UserSocialService {
|
||||
|
||||
/**
|
||||
* 根据来源和开放 ID 查询
|
||||
*
|
||||
* @param source
|
||||
* 来源
|
||||
* @param openId
|
||||
* 开放 ID
|
||||
* @return 用户社会化关联信息
|
||||
*/
|
||||
UserSocialDO getBySourceAndOpenId(String source, String openId);
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*
|
||||
* @param userSocial
|
||||
* 用户社会化关联信息
|
||||
*/
|
||||
void saveOrUpdate(UserSocialDO userSocial);
|
||||
}
|
@@ -178,6 +178,11 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO,
|
||||
return new HashSet<>(BeanUtil.copyToList(roleList, RoleDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDO getByCode(String code) {
|
||||
return baseMapper.lambdaQuery().eq(RoleDO::getCode, code).one();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查名称是否存在
|
||||
*
|
||||
|
@@ -18,9 +18,7 @@ package top.charles7c.cnadmin.system.service.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -82,6 +80,13 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserVO,
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
|
||||
@Override
|
||||
public Long save(UserDO user) {
|
||||
user.setStatus(DisEnableStatusEnum.ENABLE);
|
||||
baseMapper.insert(user);
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long add(UserRequest request) {
|
||||
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.cnadmin.system.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import top.charles7c.cnadmin.system.mapper.UserSocialMapper;
|
||||
import top.charles7c.cnadmin.system.model.entity.UserSocialDO;
|
||||
import top.charles7c.cnadmin.system.service.UserSocialService;
|
||||
|
||||
/**
|
||||
* 用户社会化关联业务实现
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/10/11 22:10
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserSocialServiceImpl implements UserSocialService {
|
||||
|
||||
private final UserSocialMapper baseMapper;
|
||||
|
||||
@Override
|
||||
public UserSocialDO getBySourceAndOpenId(String source, String openId) {
|
||||
return baseMapper.selectBySourceAndOpenId(source, openId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveOrUpdate(UserSocialDO userSocial) {
|
||||
if (null == userSocial.getCreateTime()) {
|
||||
baseMapper.insert(userSocial);
|
||||
} else {
|
||||
baseMapper.lambdaUpdate().set(UserSocialDO::getMetaJson, userSocial.getMetaJson())
|
||||
.set(UserSocialDO::getLastLoginTime, userSocial.getLastLoginTime())
|
||||
.eq(UserSocialDO::getSource, userSocial.getSource()).eq(UserSocialDO::getOpenId, userSocial.getOpenId())
|
||||
.update();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.charles7c.cnadmin.system.mapper.UserSocialMapper">
|
||||
<select id="selectBySourceAndOpenId"
|
||||
resultType="top.charles7c.cnadmin.system.model.entity.UserSocialDO">
|
||||
SELECT t1.*
|
||||
FROM `sys_user_social` AS t1
|
||||
LEFT JOIN `sys_user` AS t2 ON t2.`id` = t1.`user_id`
|
||||
WHERE t1.`source` = #{source} AND t1.`open_id` = #{openId}
|
||||
</select>
|
||||
</mapper>
|
Reference in New Issue
Block a user