From 0f09fce119bd6f4bc664e29a7c2b2d29b41a8da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E6=B2=90?= Date: Tue, 30 Aug 2022 22:39:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=9F=AD=E4=BF=A1=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/net/maku/api/module/message/SmsApi.java | 39 +++++++ fast-boot-module/fast-boot-message/pom.xml | 6 + .../main/java/net/maku/message/api/SmsApiImpl.java | 55 ++++++++++ .../java/net/maku/message/cache/SmsSendCache.java | 43 ++++++++ .../security/service/FastUserDetailsService.java | 95 ---------------- .../service/MobileUserDetailsServiceImpl.java | 33 ++++++ .../service/MobileVerifyCodeServiceImpl.java | 22 ++++ .../security/service/UserDetailsServiceImpl.java | 33 ++++++ .../maku/system/controller/SysAuthController.java | 87 +++++---------- .../net/maku/system/service/SysAuthService.java | 41 +++++++ .../net/maku/system/service/SysCaptchaService.java | 7 +- .../maku/system/service/SysUserDetailsService.java | 12 ++ .../net/maku/system/service/SysUserService.java | 7 +- .../system/service/impl/SysAuthServiceImpl.java | 122 +++++++++++++++++++++ .../system/service/impl/SysCaptchaServiceImpl.java | 25 +++-- .../service/impl/SysUserDetailsServiceImpl.java | 86 +++++++++++++++ .../system/service/impl/SysUserServiceImpl.java | 20 ++-- .../java/net/maku/system/vo/SysAccountLoginVO.java | 29 +++++ .../main/java/net/maku/system/vo/SysCaptchaVO.java | 23 ++++ .../main/java/net/maku/system/vo/SysLoginVO.java | 29 ----- .../java/net/maku/system/vo/SysMobileLoginVO.java | 23 ++++ fast-boot-system/src/main/resources/auth.yml | 2 + 22 files changed, 631 insertions(+), 208 deletions(-) create mode 100644 fast-boot-api/src/main/java/net/maku/api/module/message/SmsApi.java create mode 100644 fast-boot-module/fast-boot-message/src/main/java/net/maku/message/api/SmsApiImpl.java create mode 100644 fast-boot-module/fast-boot-message/src/main/java/net/maku/message/cache/SmsSendCache.java delete mode 100644 fast-boot-system/src/main/java/net/maku/security/service/FastUserDetailsService.java create mode 100644 fast-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java create mode 100644 fast-boot-system/src/main/java/net/maku/security/service/MobileVerifyCodeServiceImpl.java create mode 100644 fast-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/service/SysAuthService.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/vo/SysAccountLoginVO.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/vo/SysCaptchaVO.java delete mode 100644 fast-boot-system/src/main/java/net/maku/system/vo/SysLoginVO.java create mode 100644 fast-boot-system/src/main/java/net/maku/system/vo/SysMobileLoginVO.java diff --git a/fast-boot-api/src/main/java/net/maku/api/module/message/SmsApi.java b/fast-boot-api/src/main/java/net/maku/api/module/message/SmsApi.java new file mode 100644 index 0000000..48ce9c0 --- /dev/null +++ b/fast-boot-api/src/main/java/net/maku/api/module/message/SmsApi.java @@ -0,0 +1,39 @@ +package net.maku.api.module.message; + +import java.util.Map; + +/** + * 短信服务API + * + * @author 阿沐 babamu@126.com + */ +public interface SmsApi { + + /** + * 发送短信 + * + * @param mobile 手机号 + * @param params 参数 + * @return 是否发送成功 + */ + boolean send(String mobile, Map params); + + /** + * 发送短信 + * + * @param mobile 手机号 + * @param key 参数KEY + * @param value 参数Value + * @return 是否发送成功 + */ + boolean sendCode(String mobile, String key, String value); + + /** + * 效验短信验证码 + * + * @param mobile 手机号 + * @param code 验证码 + * @return 是否效验成功 + */ + boolean verifyCode(String mobile, String code); +} diff --git a/fast-boot-module/fast-boot-message/pom.xml b/fast-boot-module/fast-boot-message/pom.xml index de65482..0cbc3a1 100644 --- a/fast-boot-module/fast-boot-message/pom.xml +++ b/fast-boot-module/fast-boot-message/pom.xml @@ -16,6 +16,11 @@ ${revision} + net.maku + fast-boot-api + ${revision} + + com.aliyun dysmsapi20170525 @@ -31,6 +36,7 @@ com.qiniu qiniu-java-sdk + \ No newline at end of file diff --git a/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/api/SmsApiImpl.java b/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/api/SmsApiImpl.java new file mode 100644 index 0000000..1c7fce1 --- /dev/null +++ b/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/api/SmsApiImpl.java @@ -0,0 +1,55 @@ +package net.maku.message.api; + +import lombok.AllArgsConstructor; +import net.maku.api.module.message.SmsApi; +import net.maku.message.cache.SmsSendCache; +import net.maku.message.sms.service.SmsService; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 短信服务Api + * + * @author 阿沐 babamu@126.com + */ +@Component +@AllArgsConstructor +public class SmsApiImpl implements SmsApi { + private final SmsService smsService; + private final SmsSendCache smsSendCache; + + @Override + public boolean send(String mobile, Map params) { + return smsService.send(mobile, params); + } + + @Override + public boolean sendCode(String mobile, String key, String value) { + // 短信参数 + Map params = new HashMap<>(); + params.put(key, value); + + // 发送短信 + boolean flag = smsService.send(mobile, params); + if (flag) { + smsSendCache.saveCode(mobile, value); + } + return flag; + } + + @Override + public boolean verifyCode(String mobile, String code) { + String value = smsSendCache.getCode(mobile); + if (value != null) { + // 删除短信验证码 + smsSendCache.deleteCode(mobile); + + // 效验 + return value.equalsIgnoreCase(code); + } + + return false; + } +} diff --git a/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/cache/SmsSendCache.java b/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/cache/SmsSendCache.java new file mode 100644 index 0000000..de13918 --- /dev/null +++ b/fast-boot-module/fast-boot-message/src/main/java/net/maku/message/cache/SmsSendCache.java @@ -0,0 +1,43 @@ +package net.maku.message.cache; + +import lombok.AllArgsConstructor; +import net.maku.framework.common.cache.RedisCache; +import org.springframework.stereotype.Service; + +/** + * 短信发送 Cache + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class SmsSendCache { + private final RedisCache redisCache; + + /** + * 获取发送手机短信验证码KEY + * + * @param mobile 手机号 + * @return KEY + */ + private String getCodeKey(String mobile) { + return "message:sms:code" + mobile; + } + + public void saveCode(String mobile, String code) { + String key = getCodeKey(mobile); + + // 保存到Redis,有效期10分钟 + redisCache.set(key, code, 10 * 60); + } + + public String getCode(String mobile) { + String key = getCodeKey(mobile); + return (String) redisCache.get(key); + } + + public void deleteCode(String mobile) { + String key = getCodeKey(mobile); + redisCache.delete(key); + } +} diff --git a/fast-boot-system/src/main/java/net/maku/security/service/FastUserDetailsService.java b/fast-boot-system/src/main/java/net/maku/security/service/FastUserDetailsService.java deleted file mode 100644 index 9402b38..0000000 --- a/fast-boot-system/src/main/java/net/maku/security/service/FastUserDetailsService.java +++ /dev/null @@ -1,95 +0,0 @@ -package net.maku.security.service; - -import lombok.AllArgsConstructor; -import net.maku.framework.security.user.UserDetail; -import net.maku.system.convert.SysUserConvert; -import net.maku.system.dao.SysRoleDao; -import net.maku.system.dao.SysRoleDataScopeDao; -import net.maku.system.dao.SysUserDao; -import net.maku.system.entity.SysUserEntity; -import net.maku.system.enums.DataScopeEnum; -import net.maku.system.enums.UserStatusEnum; -import net.maku.system.service.SysMenuService; -import net.maku.system.service.SysOrgService; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * UserDetailsService - * - * @author 阿沐 babamu@126.com - */ -@Service -@AllArgsConstructor -public class FastUserDetailsService implements UserDetailsService { - private final SysMenuService sysMenuService; - private final SysOrgService sysOrgService; - private final SysUserDao sysUserDao; - private final SysRoleDao sysRoleDao; - private final SysRoleDataScopeDao sysRoleDataScopeDao; - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - SysUserEntity userEntity = sysUserDao.getByUsername(username); - if (userEntity == null) { - throw new UsernameNotFoundException("用户名或密码错误"); - } - - // 转换成UserDetail对象 - UserDetail userDetail = SysUserConvert.INSTANCE.convertDetail(userEntity); - - // 账号不可用 - if (userEntity.getStatus() == UserStatusEnum.DISABLE.getValue()) { - userDetail.setEnabled(false); - } - - // 数据权限范围 - List dataScopeList = getDataScope(userDetail); - userDetail.setDataScopeList(dataScopeList); - - // 用户权限列表 - Set authoritySet = sysMenuService.getUserAuthority(userDetail); - userDetail.setAuthoritySet(authoritySet); - - return userDetail; - } - - private List getDataScope(UserDetail userDetail) { - Integer dataScope = sysRoleDao.getDataScopeByUserId(userDetail.getId()); - if (dataScope == null) { - return new ArrayList<>(); - } - - if (dataScope.equals(DataScopeEnum.ALL.getValue())) { - // 全部数据权限,则返回null - return null; - } else if (dataScope.equals(DataScopeEnum.DEPT_AND_CHILD.getValue())) { - // 本部门及子部门数据 - List dataScopeList = sysOrgService.getSubOrgIdList(userDetail.getOrgId()); - // 自定义数据权限范围 - dataScopeList.addAll(sysRoleDataScopeDao.getDataScopeList(userDetail.getId())); - - return dataScopeList; - } else if (dataScope.equals(DataScopeEnum.DEPT_ONLY.getValue())) { - // 本部门数据 - List dataScopeList = new ArrayList<>(); - dataScopeList.add(userDetail.getOrgId()); - // 自定义数据权限范围 - dataScopeList.addAll(sysRoleDataScopeDao.getDataScopeList(userDetail.getId())); - - return dataScopeList; - } else if (dataScope.equals(DataScopeEnum.CUSTOM.getValue())) { - // 自定义数据权限范围 - return sysRoleDataScopeDao.getDataScopeList(userDetail.getId()); - } - - return new ArrayList<>(); - } - -} diff --git a/fast-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java b/fast-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java new file mode 100644 index 0000000..6e29dc3 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java @@ -0,0 +1,33 @@ +package net.maku.security.service; + +import lombok.AllArgsConstructor; +import net.maku.framework.security.mobile.MobileUserDetailsService; +import net.maku.system.dao.SysUserDao; +import net.maku.system.entity.SysUserEntity; +import net.maku.system.service.SysUserDetailsService; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * 手机验证码登录 MobileUserDetailsService + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class MobileUserDetailsServiceImpl implements MobileUserDetailsService { + private final SysUserDetailsService sysUserDetailsService; + private final SysUserDao sysUserDao; + + @Override + public UserDetails loadUserByMobile(String mobile) throws UsernameNotFoundException { + SysUserEntity userEntity = sysUserDao.getByMobile(mobile); + if (userEntity == null) { + throw new UsernameNotFoundException("手机号或验证码错误"); + } + + return sysUserDetailsService.getUserDetails(userEntity); + } + +} diff --git a/fast-boot-system/src/main/java/net/maku/security/service/MobileVerifyCodeServiceImpl.java b/fast-boot-system/src/main/java/net/maku/security/service/MobileVerifyCodeServiceImpl.java new file mode 100644 index 0000000..1d3481c --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/security/service/MobileVerifyCodeServiceImpl.java @@ -0,0 +1,22 @@ +package net.maku.security.service; + +import lombok.AllArgsConstructor; +import net.maku.api.module.message.SmsApi; +import net.maku.framework.security.mobile.MobileVerifyCodeService; +import org.springframework.stereotype.Service; + +/** + * 短信验证码效验 + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class MobileVerifyCodeServiceImpl implements MobileVerifyCodeService { + private final SmsApi smsApi; + + @Override + public boolean verifyCode(String mobile, String code) { + return smsApi.verifyCode(mobile, code); + } +} diff --git a/fast-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java b/fast-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..9a74ae0 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java @@ -0,0 +1,33 @@ +package net.maku.security.service; + +import lombok.AllArgsConstructor; +import net.maku.system.dao.SysUserDao; +import net.maku.system.entity.SysUserEntity; +import net.maku.system.service.SysUserDetailsService; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * 账号登录 UserDetailsService + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class UserDetailsServiceImpl implements UserDetailsService { + private final SysUserDetailsService sysUserDetailsService; + private final SysUserDao sysUserDao; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + SysUserEntity userEntity = sysUserDao.getByUsername(username); + if (userEntity == null) { + throw new UsernameNotFoundException("用户名或密码错误"); + } + + return sysUserDetailsService.getUserDetails(userEntity); + } + +} diff --git a/fast-boot-system/src/main/java/net/maku/system/controller/SysAuthController.java b/fast-boot-system/src/main/java/net/maku/system/controller/SysAuthController.java index 7dd2b11..0446336 100644 --- a/fast-boot-system/src/main/java/net/maku/system/controller/SysAuthController.java +++ b/fast-boot-system/src/main/java/net/maku/system/controller/SysAuthController.java @@ -1,28 +1,19 @@ package net.maku.system.controller; -import cn.hutool.core.lang.UUID; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; -import net.maku.framework.common.constant.Constant; import net.maku.framework.common.utils.Result; -import net.maku.framework.security.cache.TokenStoreCache; -import net.maku.framework.security.user.UserDetail; import net.maku.framework.security.utils.TokenUtils; -import net.maku.system.enums.LoginOperationEnum; +import net.maku.system.service.SysAuthService; import net.maku.system.service.SysCaptchaService; -import net.maku.system.service.SysLogLoginService; -import net.maku.system.vo.SysLoginVO; +import net.maku.system.vo.SysAccountLoginVO; +import net.maku.system.vo.SysCaptchaVO; +import net.maku.system.vo.SysMobileLoginVO; import net.maku.system.vo.SysTokenVO; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; /** * 认证管理 @@ -35,72 +26,44 @@ import java.util.Map; @AllArgsConstructor public class SysAuthController { private final SysCaptchaService sysCaptchaService; - private final TokenStoreCache tokenStoreCache; - private final AuthenticationManager authenticationManager; - private final SysLogLoginService sysLogLoginService; + private final SysAuthService sysAuthService; @GetMapping("captcha") @Operation(summary = "验证码") - public Result> captcha() { - // 生成key - String key = UUID.randomUUID().toString(); - // 生成base64验证码 - String image = sysCaptchaService.generate(key); + public Result captcha() { + SysCaptchaVO captchaVO = sysCaptchaService.generate(); - // 封装返回数据 - Map data = new HashMap<>(); - data.put("key", key); - data.put("image", image); - - return Result.ok(data); + return Result.ok(captchaVO); } @PostMapping("login") - @Operation(summary = "登录") - public Result login(@RequestBody SysLoginVO login) { - // 验证码效验 - boolean flag = sysCaptchaService.validate(login.getKey(), login.getCaptcha()); - if (!flag) { - // 保存登录日志 - sysLogLoginService.save(login.getUsername(), Constant.FAIL, LoginOperationEnum.CAPTCHA_FAIL.getValue()); + @Operation(summary = "账号密码登录") + public Result login(@RequestBody SysAccountLoginVO login) { + SysTokenVO token = sysAuthService.loginByAccount(login); - return Result.error("验证码错误"); - } + return Result.ok(token); + } - Authentication authentication; - try { - // 用户认证 - authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(login.getUsername(), login.getPassword())); - } catch (BadCredentialsException e) { - return Result.error("用户名密码错误"); - } + @PostMapping("send/code") + @Operation(summary = "发送短信验证码") + public Result sendCode(String mobile) { + sysAuthService.sendCode(mobile); - // 用户信息 - UserDetail user = (UserDetail) authentication.getPrincipal(); + return Result.ok(); + } - // 生成 accessToken - String accessToken = TokenUtils.generator(); + @PostMapping("mobile") + @Operation(summary = "手机号登录") + public Result mobile(@RequestBody SysMobileLoginVO login) { + SysTokenVO token = sysAuthService.loginByMobile(login); - // 保存用户信息到缓存 - tokenStoreCache.saveUser(accessToken, user); - - return Result.ok(new SysTokenVO(accessToken)); + return Result.ok(token); } @PostMapping("logout") @Operation(summary = "退出") public Result logout(HttpServletRequest request) { - String accessToken = TokenUtils.getAccessToken(request); - - // 用户信息 - UserDetail user = tokenStoreCache.getUser(accessToken); - - // 删除用户信息 - tokenStoreCache.deleteUser(accessToken); - - // 保存登录日志 - sysLogLoginService.save(user.getUsername(), Constant.SUCCESS, LoginOperationEnum.LOGOUT_SUCCESS.getValue()); + sysAuthService.logout(TokenUtils.getAccessToken(request)); return Result.ok(); } diff --git a/fast-boot-system/src/main/java/net/maku/system/service/SysAuthService.java b/fast-boot-system/src/main/java/net/maku/system/service/SysAuthService.java new file mode 100644 index 0000000..c307402 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/system/service/SysAuthService.java @@ -0,0 +1,41 @@ +package net.maku.system.service; + +import net.maku.system.vo.SysAccountLoginVO; +import net.maku.system.vo.SysMobileLoginVO; +import net.maku.system.vo.SysTokenVO; + +/** + * 权限认证服务 + * + * @author 阿沐 babamu@126.com + */ +public interface SysAuthService { + + /** + * 账号密码登录 + * + * @param login 登录信息 + */ + SysTokenVO loginByAccount(SysAccountLoginVO login); + + /** + * 手机短信登录 + * + * @param login 登录信息 + */ + SysTokenVO loginByMobile(SysMobileLoginVO login); + + /** + * 发送手机验证码 + * + * @param mobile 手机号 + */ + void sendCode(String mobile); + + /** + * 退出登录 + * + * @param accessToken accessToken + */ + void logout(String accessToken); +} diff --git a/fast-boot-system/src/main/java/net/maku/system/service/SysCaptchaService.java b/fast-boot-system/src/main/java/net/maku/system/service/SysCaptchaService.java index 91e1d0a..21e46d1 100644 --- a/fast-boot-system/src/main/java/net/maku/system/service/SysCaptchaService.java +++ b/fast-boot-system/src/main/java/net/maku/system/service/SysCaptchaService.java @@ -1,5 +1,7 @@ package net.maku.system.service; +import net.maku.system.vo.SysCaptchaVO; + /** * 验证码 * @@ -8,11 +10,8 @@ package net.maku.system.service; public interface SysCaptchaService { /** * 生成验证码 - * - * @param key key - * @return 返回base64图片验证码 */ - String generate(String key); + SysCaptchaVO generate(); /** * 验证码效验 diff --git a/fast-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java b/fast-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java new file mode 100644 index 0000000..03b01e1 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java @@ -0,0 +1,12 @@ +package net.maku.system.service; + +import net.maku.system.entity.SysUserEntity; +import org.springframework.security.core.userdetails.UserDetails; + +public interface SysUserDetailsService { + + /** + * 获取 UserDetails 对象 + */ + UserDetails getUserDetails(SysUserEntity userEntity); +} diff --git a/fast-boot-system/src/main/java/net/maku/system/service/SysUserService.java b/fast-boot-system/src/main/java/net/maku/system/service/SysUserService.java index 51591a2..b4dd673 100644 --- a/fast-boot-system/src/main/java/net/maku/system/service/SysUserService.java +++ b/fast-boot-system/src/main/java/net/maku/system/service/SysUserService.java @@ -24,10 +24,13 @@ public interface SysUserService extends BaseService { void delete(List idList); + SysUserVO getByMobile(String mobile); + /** * 修改密码 - * @param id 用户ID - * @param newPassword 新密码 + * + * @param id 用户ID + * @param newPassword 新密码 */ void updatePassword(Long id, String newPassword); diff --git a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java new file mode 100644 index 0000000..41769c9 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java @@ -0,0 +1,122 @@ +package net.maku.system.service.impl; + +import cn.hutool.core.util.RandomUtil; +import lombok.AllArgsConstructor; +import net.maku.api.module.message.SmsApi; +import net.maku.framework.common.constant.Constant; +import net.maku.framework.common.exception.FastException; +import net.maku.framework.security.cache.TokenStoreCache; +import net.maku.framework.security.mobile.MobileAuthenticationToken; +import net.maku.framework.security.user.UserDetail; +import net.maku.framework.security.utils.TokenUtils; +import net.maku.system.enums.LoginOperationEnum; +import net.maku.system.service.SysAuthService; +import net.maku.system.service.SysCaptchaService; +import net.maku.system.service.SysLogLoginService; +import net.maku.system.service.SysUserService; +import net.maku.system.vo.SysAccountLoginVO; +import net.maku.system.vo.SysMobileLoginVO; +import net.maku.system.vo.SysTokenVO; +import net.maku.system.vo.SysUserVO; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +/** + * 权限认证服务 + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class SysAuthServiceImpl implements SysAuthService { + private final SysCaptchaService sysCaptchaService; + private final TokenStoreCache tokenStoreCache; + private final AuthenticationManager authenticationManager; + private final SysLogLoginService sysLogLoginService; + private final SysUserService sysUserService; + private final SmsApi smsApi; + + @Override + public SysTokenVO loginByAccount(SysAccountLoginVO login) { + // 验证码效验 + boolean flag = sysCaptchaService.validate(login.getKey(), login.getCaptcha()); + if (!flag) { + // 保存登录日志 + sysLogLoginService.save(login.getUsername(), Constant.FAIL, LoginOperationEnum.CAPTCHA_FAIL.getValue()); + + throw new FastException("验证码错误"); + } + + Authentication authentication; + try { + // 用户认证 + authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(login.getUsername(), login.getPassword())); + } catch (BadCredentialsException e) { + throw new FastException("用户名或密码错误"); + } + + // 用户信息 + UserDetail user = (UserDetail) authentication.getPrincipal(); + + // 生成 accessToken + String accessToken = TokenUtils.generator(); + + // 保存用户信息到缓存 + tokenStoreCache.saveUser(accessToken, user); + + return new SysTokenVO(accessToken); + } + + @Override + public SysTokenVO loginByMobile(SysMobileLoginVO login) { + Authentication authentication; + try { + // 用户认证 + authentication = authenticationManager.authenticate( + new MobileAuthenticationToken(login.getMobile(), login.getCode())); + } catch (BadCredentialsException e) { + throw new FastException("手机号或验证码错误"); + } + + // 用户信息 + UserDetail user = (UserDetail) authentication.getPrincipal(); + + // 生成 accessToken + String accessToken = TokenUtils.generator(); + + // 保存用户信息到缓存 + tokenStoreCache.saveUser(accessToken, user); + + return new SysTokenVO(accessToken); + } + + @Override + public void sendCode(String mobile) { + // 生成6位验证码 + String code = RandomUtil.randomNumbers(6); + + SysUserVO user = sysUserService.getByMobile(mobile); + if (user == null) { + throw new FastException("手机号未注册"); + } + + // 发送短信 + smsApi.sendCode(mobile, "code", code); + } + + @Override + public void logout(String accessToken) { + // 用户信息 + UserDetail user = tokenStoreCache.getUser(accessToken); + + // 删除用户信息 + tokenStoreCache.deleteUser(accessToken); + + // 保存登录日志 + sysLogLoginService.save(user.getUsername(), Constant.SUCCESS, LoginOperationEnum.LOGOUT_SUCCESS.getValue()); + } +} diff --git a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysCaptchaServiceImpl.java b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysCaptchaServiceImpl.java index 4bdd31d..49054f3 100644 --- a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysCaptchaServiceImpl.java +++ b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysCaptchaServiceImpl.java @@ -1,5 +1,6 @@ package net.maku.system.service.impl; +import cn.hutool.core.lang.UUID; import cn.hutool.core.util.StrUtil; import com.wf.captcha.SpecCaptcha; import com.wf.captcha.base.Captcha; @@ -7,6 +8,7 @@ import lombok.AllArgsConstructor; import net.maku.framework.common.cache.RedisCache; import net.maku.framework.common.cache.RedisKeys; import net.maku.system.service.SysCaptchaService; +import net.maku.system.vo.SysCaptchaVO; import org.springframework.stereotype.Service; /** @@ -20,17 +22,26 @@ public class SysCaptchaServiceImpl implements SysCaptchaService { private final RedisCache redisCache; @Override - public String generate(String key) { + public SysCaptchaVO generate() { + // 生成验证码key + String key = UUID.randomUUID().toString(); + // 生成验证码 SpecCaptcha captcha = new SpecCaptcha(150, 40); captcha.setLen(5); captcha.setCharType(Captcha.TYPE_DEFAULT); + String image = captcha.toBase64(); // 保存到缓存 - key = RedisKeys.getCaptchaKey(key); - redisCache.set(key, captcha.text(), 300); + String redisKey = RedisKeys.getCaptchaKey(key); + redisCache.set(redisKey, captcha.text(), 300); - return captcha.toBase64(); + // 封装返回数据 + SysCaptchaVO captchaVO = new SysCaptchaVO(); + captchaVO.setKey(key); + captchaVO.setImage(image); + + return captchaVO; } @Override @@ -43,11 +54,7 @@ public class SysCaptchaServiceImpl implements SysCaptchaService { String captcha = getCache(key); // 效验成功 - if (code.equalsIgnoreCase(captcha)) { - return true; - } - - return false; + return code.equalsIgnoreCase(captcha); } private String getCache(String key) { diff --git a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java new file mode 100644 index 0000000..960ea01 --- /dev/null +++ b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java @@ -0,0 +1,86 @@ +package net.maku.system.service.impl; + +import lombok.AllArgsConstructor; +import net.maku.framework.security.user.UserDetail; +import net.maku.system.convert.SysUserConvert; +import net.maku.system.dao.SysRoleDao; +import net.maku.system.dao.SysRoleDataScopeDao; +import net.maku.system.entity.SysUserEntity; +import net.maku.system.enums.DataScopeEnum; +import net.maku.system.enums.UserStatusEnum; +import net.maku.system.service.SysMenuService; +import net.maku.system.service.SysOrgService; +import net.maku.system.service.SysUserDetailsService; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 用户 UserDetails 信息 + * + * @author 阿沐 babamu@126.com + */ +@Service +@AllArgsConstructor +public class SysUserDetailsServiceImpl implements SysUserDetailsService { + private final SysMenuService sysMenuService; + private final SysOrgService sysOrgService; + private final SysRoleDao sysRoleDao; + private final SysRoleDataScopeDao sysRoleDataScopeDao; + + @Override + public UserDetails getUserDetails(SysUserEntity userEntity) { + // 转换成UserDetail对象 + UserDetail userDetail = SysUserConvert.INSTANCE.convertDetail(userEntity); + + // 账号不可用 + if (userEntity.getStatus() == UserStatusEnum.DISABLE.getValue()) { + userDetail.setEnabled(false); + } + + // 数据权限范围 + List dataScopeList = getDataScope(userDetail); + userDetail.setDataScopeList(dataScopeList); + + // 用户权限列表 + Set authoritySet = sysMenuService.getUserAuthority(userDetail); + userDetail.setAuthoritySet(authoritySet); + + return userDetail; + } + + private List getDataScope(UserDetail userDetail) { + Integer dataScope = sysRoleDao.getDataScopeByUserId(userDetail.getId()); + if (dataScope == null) { + return new ArrayList<>(); + } + + if (dataScope.equals(DataScopeEnum.ALL.getValue())) { + // 全部数据权限,则返回null + return null; + } else if (dataScope.equals(DataScopeEnum.DEPT_AND_CHILD.getValue())) { + // 本部门及子部门数据 + List dataScopeList = sysOrgService.getSubOrgIdList(userDetail.getOrgId()); + // 自定义数据权限范围 + dataScopeList.addAll(sysRoleDataScopeDao.getDataScopeList(userDetail.getId())); + + return dataScopeList; + } else if (dataScope.equals(DataScopeEnum.DEPT_ONLY.getValue())) { + // 本部门数据 + List dataScopeList = new ArrayList<>(); + dataScopeList.add(userDetail.getOrgId()); + // 自定义数据权限范围 + dataScopeList.addAll(sysRoleDataScopeDao.getDataScopeList(userDetail.getId())); + + return dataScopeList; + } else if (dataScope.equals(DataScopeEnum.CUSTOM.getValue())) { + // 自定义数据权限范围 + return sysRoleDataScopeDao.getDataScopeList(userDetail.getId()); + } + + return new ArrayList<>(); + } +} diff --git a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java index 7c66440..c724774 100644 --- a/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java +++ b/fast-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java @@ -11,10 +11,10 @@ import net.maku.system.dao.SysUserDao; import net.maku.system.entity.SysUserEntity; import net.maku.system.enums.SuperAdminEnum; import net.maku.system.query.SysRoleUserQuery; +import net.maku.system.query.SysUserQuery; import net.maku.system.service.SysUserPostService; import net.maku.system.service.SysUserRoleService; import net.maku.system.service.SysUserService; -import net.maku.system.query.SysUserQuery; import net.maku.system.vo.SysUserVO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,7 +49,7 @@ public class SysUserServiceImpl extends BaseServiceImpl(SysUserConvert.INSTANCE.convertList(list), page.getTotal()); } - private Map getParams(SysUserQuery query){ + private Map getParams(SysUserQuery query) { Map params = new HashMap<>(); params.put("username", query.getUsername()); params.put("mobile", query.getMobile()); @@ -62,7 +62,6 @@ public class SysUserServiceImpl extends BaseServiceImpl