diff --git a/maku-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java b/maku-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java index 439c504..9a294ab 100644 --- a/maku-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/security/service/MobileUserDetailsServiceImpl.java @@ -2,6 +2,7 @@ package net.maku.security.service; import lombok.AllArgsConstructor; import net.maku.framework.security.mobile.MobileUserDetailsService; +import net.maku.system.convert.SysUserConvert; import net.maku.system.dao.SysUserDao; import net.maku.system.entity.SysUserEntity; import net.maku.system.service.SysUserDetailsService; @@ -28,7 +29,7 @@ public class MobileUserDetailsServiceImpl implements MobileUserDetailsService { throw new UsernameNotFoundException("手机号或验证码错误"); } - return sysUserDetailsService.getUserDetails(userEntity); + return sysUserDetailsService.getUserDetails(SysUserConvert.INSTANCE.convertDetail(userEntity)); } } diff --git a/maku-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java b/maku-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java index 662c681..a7e0dbf 100644 --- a/maku-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/security/service/UserDetailsServiceImpl.java @@ -1,6 +1,7 @@ package net.maku.security.service; import lombok.AllArgsConstructor; +import net.maku.system.convert.SysUserConvert; import net.maku.system.dao.SysUserDao; import net.maku.system.entity.SysUserEntity; import net.maku.system.service.SysUserDetailsService; @@ -28,7 +29,7 @@ public class UserDetailsServiceImpl implements UserDetailsService { throw new UsernameNotFoundException("用户名或密码错误"); } - return sysUserDetailsService.getUserDetails(userEntity); + return sysUserDetailsService.getUserDetails(SysUserConvert.INSTANCE.convertDetail(userEntity)); } } diff --git a/maku-boot-system/src/main/java/net/maku/system/convert/SysUserTokenConvert.java b/maku-boot-system/src/main/java/net/maku/system/convert/SysUserTokenConvert.java new file mode 100644 index 0000000..e13551b --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/convert/SysUserTokenConvert.java @@ -0,0 +1,21 @@ +package net.maku.system.convert; + +import net.maku.system.entity.SysUserTokenEntity; +import net.maku.system.vo.SysUserTokenVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 用户Token + * + * @author 阿沐 babamu@126.com + */ +@Mapper +public interface SysUserTokenConvert { + SysUserTokenConvert INSTANCE = Mappers.getMapper(SysUserTokenConvert.class); + + SysUserTokenEntity convert(SysUserTokenVO vo); + + SysUserTokenVO convert(SysUserTokenEntity entity); + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/dao/SysRoleDao.java b/maku-boot-system/src/main/java/net/maku/system/dao/SysRoleDao.java index 28dc659..ed64e93 100644 --- a/maku-boot-system/src/main/java/net/maku/system/dao/SysRoleDao.java +++ b/maku-boot-system/src/main/java/net/maku/system/dao/SysRoleDao.java @@ -5,9 +5,11 @@ import net.maku.system.entity.SysRoleEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.util.List; + /** * 角色管理 - * + * * @author 阿沐 babamu@126.com * MAKU */ @@ -19,4 +21,9 @@ public interface SysRoleDao extends BaseDao { */ Integer getDataScopeByUserId(@Param("userId") Long userId); + /** + * 根据用户ID,获取用户角色编码 + */ + List geRoleCodeByUserId(@Param("userId") Long userId); + } diff --git a/maku-boot-system/src/main/java/net/maku/system/dao/SysUserTokenDao.java b/maku-boot-system/src/main/java/net/maku/system/dao/SysUserTokenDao.java new file mode 100644 index 0000000..773d699 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/dao/SysUserTokenDao.java @@ -0,0 +1,37 @@ +package net.maku.system.dao; + +import net.maku.framework.mybatis.dao.BaseDao; +import net.maku.system.entity.SysUserTokenEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + * 用户Token + * + * @author 阿沐 babamu@126.com + */ +@Mapper +public interface SysUserTokenDao extends BaseDao { + + /** + * 根据角色ID,查询在线用户 access_token 列表 + * + * @param roleId 角色ID + * @param time 当前时间 + * @return 返回 access_token 列表 + */ + List getOnlineAccessTokenListByRoleId(@Param("roleId") Long roleId, @Param("time") Date time); + + /** + * 根据用户ID,查询在线用户 access_token 列表 + * + * @param userId 用户ID + * @param time 当前时间 + * @return 返回 access_token 列表 + */ + List getOnlineAccessTokenListByUserId(@Param("userId") Long userId, @Param("time") Date time); + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/entity/SysUserTokenEntity.java b/maku-boot-system/src/main/java/net/maku/system/entity/SysUserTokenEntity.java new file mode 100644 index 0000000..8ab7332 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/entity/SysUserTokenEntity.java @@ -0,0 +1,61 @@ +package net.maku.system.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 用户Token + * + * @author 阿沐 babamu@126.com + * MAKU + */ + +@Data +@TableName("sys_user_token") +public class SysUserTokenEntity { + + @TableId + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * accessToken + */ + private String accessToken; + + /** + * accessToken 过期时间 + */ + private Date accessTokenExpire; + + /** + * refreshToken + */ + private String refreshToken; + + /** + * refreshToken 过期时间 + */ + private Date refreshTokenExpire; + + /** + * 租户ID + */ + private Long tenantId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/service/SysAuthService.java b/maku-boot-system/src/main/java/net/maku/system/service/SysAuthService.java index 4f6edb7..6ec5c7f 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/SysAuthService.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/SysAuthService.java @@ -1,8 +1,9 @@ package net.maku.system.service; +import net.maku.system.vo.AccessTokenVO; import net.maku.system.vo.SysAccountLoginVO; import net.maku.system.vo.SysMobileLoginVO; -import net.maku.system.vo.SysTokenVO; +import net.maku.system.vo.SysUserTokenVO; /** * 权限认证服务 @@ -17,14 +18,14 @@ public interface SysAuthService { * * @param login 登录信息 */ - SysTokenVO loginByAccount(SysAccountLoginVO login); + SysUserTokenVO loginByAccount(SysAccountLoginVO login); /** * 手机短信登录 * * @param login 登录信息 */ - SysTokenVO loginByMobile(SysMobileLoginVO login); + SysUserTokenVO loginByMobile(SysMobileLoginVO login); /** * 发送手机验证码 @@ -34,6 +35,13 @@ public interface SysAuthService { boolean sendCode(String mobile); /** + * 根据刷新Token,获取AccessToken + * + * @param refreshToken refreshToken + */ + AccessTokenVO getAccessToken(String refreshToken); + + /** * 退出登录 * * @param accessToken accessToken diff --git a/maku-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java b/maku-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java index 03b01e1..8f128d1 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/SysUserDetailsService.java @@ -1,12 +1,12 @@ package net.maku.system.service; -import net.maku.system.entity.SysUserEntity; +import net.maku.framework.security.user.UserDetail; import org.springframework.security.core.userdetails.UserDetails; public interface SysUserDetailsService { /** - * 获取 UserDetails 对象 + * 获取 UserDetails 对象,设置用户权限信息 */ - UserDetails getUserDetails(SysUserEntity userEntity); + UserDetails getUserDetails(UserDetail userDetail); } diff --git a/maku-boot-system/src/main/java/net/maku/system/service/SysUserTokenService.java b/maku-boot-system/src/main/java/net/maku/system/service/SysUserTokenService.java new file mode 100644 index 0000000..7b551e3 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/service/SysUserTokenService.java @@ -0,0 +1,51 @@ +package net.maku.system.service; + +import net.maku.framework.mybatis.service.BaseService; +import net.maku.system.entity.SysUserTokenEntity; +import net.maku.system.vo.SysUserTokenVO; + + +/** + * 用户Token + * + * @author 阿沐 babamu@126.com + */ +public interface SysUserTokenService extends BaseService { + + /** + * 根据用户ID,生成用户Token + * + * @param userId 用户ID + * @return 用户Token + */ + SysUserTokenVO createToken(Long userId); + + /** + * 根据refreshToken,生成新Token + * + * @param refreshToken refreshToken + * @return 用户Token + */ + SysUserTokenVO refreshToken(String refreshToken); + + /** + * Token过期 + * + * @param userId 用户ID + */ + void expireToken(Long userId); + + /** + * 根据角色ID,更新用户缓存权限 + * + * @param roleId 角色ID + */ + void updateCacheAuthByRoleId(Long roleId); + + /** + * 根据用户ID,更新用户缓存权限 + * + * @param userId 用户ID + */ + void updateCacheAuthByUserId(Long userId); +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java index 0325b87..33ce42d 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysAuthServiceImpl.java @@ -8,16 +8,9 @@ import net.maku.framework.common.exception.ServerException; 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 net.maku.system.service.*; +import net.maku.system.vo.*; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -38,10 +31,11 @@ public class SysAuthServiceImpl implements SysAuthService { private final AuthenticationManager authenticationManager; private final SysLogLoginService sysLogLoginService; private final SysUserService sysUserService; + private final SysUserTokenService sysUserTokenService; private final SmsApi smsApi; - + @Override - public SysTokenVO loginByAccount(SysAccountLoginVO login) { + public SysUserTokenVO loginByAccount(SysAccountLoginVO login) { // 验证码效验 boolean flag = sysCaptchaService.validate(login.getKey(), login.getCaptcha()); if (!flag) { @@ -64,16 +58,16 @@ public class SysAuthServiceImpl implements SysAuthService { UserDetail user = (UserDetail) authentication.getPrincipal(); // 生成 accessToken - String accessToken = TokenUtils.generator(); + SysUserTokenVO userTokenVO = sysUserTokenService.createToken(user.getId()); // 保存用户信息到缓存 - tokenStoreCache.saveUser(accessToken, user); + tokenStoreCache.saveUser(userTokenVO.getAccessToken(), user); - return new SysTokenVO(accessToken); + return userTokenVO; } @Override - public SysTokenVO loginByMobile(SysMobileLoginVO login) { + public SysUserTokenVO loginByMobile(SysMobileLoginVO login) { Authentication authentication; try { // 用户认证 @@ -87,12 +81,12 @@ public class SysAuthServiceImpl implements SysAuthService { UserDetail user = (UserDetail) authentication.getPrincipal(); // 生成 accessToken - String accessToken = TokenUtils.generator(); + SysUserTokenVO userTokenVO = sysUserTokenService.createToken(user.getId()); // 保存用户信息到缓存 - tokenStoreCache.saveUser(accessToken, user); + tokenStoreCache.saveUser(userTokenVO.getAccessToken(), user); - return new SysTokenVO(accessToken); + return userTokenVO; } @Override @@ -110,6 +104,18 @@ public class SysAuthServiceImpl implements SysAuthService { } @Override + public AccessTokenVO getAccessToken(String refreshToken) { + SysUserTokenVO token = sysUserTokenService.refreshToken(refreshToken); + + // 封装 AccessToken + AccessTokenVO accessToken = new AccessTokenVO(); + accessToken.setAccessToken(token.getAccessToken()); + accessToken.setAccessTokenExpire(token.getAccessTokenExpire()); + + return accessToken; + } + + @Override public void logout(String accessToken) { // 用户信息 UserDetail user = tokenStoreCache.getUser(accessToken); @@ -117,6 +123,9 @@ public class SysAuthServiceImpl implements SysAuthService { // 删除用户信息 tokenStoreCache.deleteUser(accessToken); + // Token过期 + sysUserTokenService.expireToken(user.getId()); + // 保存登录日志 sysLogLoginService.save(user.getUsername(), Constant.SUCCESS, LoginOperationEnum.LOGOUT_SUCCESS.getValue()); } diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysRoleServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysRoleServiceImpl.java index 49efd1e..ed1b320 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysRoleServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysRoleServiceImpl.java @@ -12,10 +12,7 @@ import net.maku.system.dao.SysRoleDao; import net.maku.system.entity.SysRoleEntity; import net.maku.system.enums.DataScopeEnum; import net.maku.system.query.SysRoleQuery; -import net.maku.system.service.SysRoleDataScopeService; -import net.maku.system.service.SysRoleMenuService; -import net.maku.system.service.SysRoleService; -import net.maku.system.service.SysUserRoleService; +import net.maku.system.service.*; import net.maku.system.vo.SysRoleDataScopeVO; import net.maku.system.vo.SysRoleVO; import org.springframework.stereotype.Service; @@ -26,96 +23,106 @@ import java.util.List; /** * 角色 - * + * * @author 阿沐 babamu@126.com * MAKU */ @Service @AllArgsConstructor public class SysRoleServiceImpl extends BaseServiceImpl implements SysRoleService { - private final SysRoleMenuService sysRoleMenuService; - private final SysRoleDataScopeService sysRoleDataScopeService; - private final SysUserRoleService sysUserRoleService; + private final SysRoleMenuService sysRoleMenuService; + private final SysRoleDataScopeService sysRoleDataScopeService; + private final SysUserRoleService sysUserRoleService; + private final SysUserTokenService sysUserTokenService; - @Override - public PageResult page(SysRoleQuery query) { - IPage page = baseMapper.selectPage(getPage(query), getWrapper(query)); + @Override + public PageResult page(SysRoleQuery query) { + IPage page = baseMapper.selectPage(getPage(query), getWrapper(query)); - return new PageResult<>(SysRoleConvert.INSTANCE.convertList(page.getRecords()), page.getTotal()); - } + return new PageResult<>(SysRoleConvert.INSTANCE.convertList(page.getRecords()), page.getTotal()); + } - @Override - public List getList(SysRoleQuery query) { - List entityList = baseMapper.selectList(getWrapper(query)); + @Override + public List getList(SysRoleQuery query) { + List entityList = baseMapper.selectList(getWrapper(query)); - return SysRoleConvert.INSTANCE.convertList(entityList); - } + return SysRoleConvert.INSTANCE.convertList(entityList); + } - private Wrapper getWrapper(SysRoleQuery query){ - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.like(StrUtil.isNotBlank(query.getName()), SysRoleEntity::getName, query.getName()); + private Wrapper getWrapper(SysRoleQuery query) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.like(StrUtil.isNotBlank(query.getName()), SysRoleEntity::getName, query.getName()); - // 数据权限 - dataScopeWrapper(wrapper); + // 数据权限 + dataScopeWrapper(wrapper); - return wrapper; - } + return wrapper; + } - @Override - @Transactional(rollbackFor = Exception.class) - public void save(SysRoleVO vo) { - SysRoleEntity entity = SysRoleConvert.INSTANCE.convert(vo); + @Override + @Transactional(rollbackFor = Exception.class) + public void save(SysRoleVO vo) { + SysRoleEntity entity = SysRoleConvert.INSTANCE.convert(vo); - // 保存角色 - entity.setDataScope(DataScopeEnum.SELF.getValue()); - baseMapper.insert(entity); + // 保存角色 + entity.setDataScope(DataScopeEnum.SELF.getValue()); + baseMapper.insert(entity); - // 保存角色菜单关系 - sysRoleMenuService.saveOrUpdate(entity.getId(), vo.getMenuIdList()); - } + // 保存角色菜单关系 + sysRoleMenuService.saveOrUpdate(entity.getId(), vo.getMenuIdList()); + } - @Override - @Transactional(rollbackFor = Exception.class) - public void update(SysRoleVO vo) { - SysRoleEntity entity = SysRoleConvert.INSTANCE.convert(vo); + @Override + @Transactional(rollbackFor = Exception.class) + public void update(SysRoleVO vo) { + SysRoleEntity entity = SysRoleConvert.INSTANCE.convert(vo); - // 更新角色 - updateById(entity); + // 更新角色 + updateById(entity); - // 更新角色菜单关系 - sysRoleMenuService.saveOrUpdate(entity.getId(), vo.getMenuIdList()); - } + // 更新角色菜单关系 + sysRoleMenuService.saveOrUpdate(entity.getId(), vo.getMenuIdList()); - @Override - @Transactional(rollbackFor = Exception.class) - public void dataScope(SysRoleDataScopeVO vo) { - SysRoleEntity entity = getById(vo.getId()); - entity.setDataScope(vo.getDataScope()); - // 更新角色 - updateById(entity); + // 更新角色对应用户的缓存权限 + sysUserTokenService.updateCacheAuthByRoleId(entity.getId()); + } - // 更新角色数据权限关系 - if(vo.getDataScope().equals(DataScopeEnum.CUSTOM.getValue())){ - sysRoleDataScopeService.saveOrUpdate(entity.getId(), vo.getOrgIdList()); - }else { - sysRoleDataScopeService.deleteByRoleIdList(Collections.singletonList(vo.getId())); - } - } + @Override + @Transactional(rollbackFor = Exception.class) + public void dataScope(SysRoleDataScopeVO vo) { + SysRoleEntity entity = getById(vo.getId()); + entity.setDataScope(vo.getDataScope()); + // 更新角色 + updateById(entity); - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(List idList) { - // 删除角色 - removeByIds(idList); + // 更新角色数据权限关系 + if (vo.getDataScope().equals(DataScopeEnum.CUSTOM.getValue())) { + sysRoleDataScopeService.saveOrUpdate(entity.getId(), vo.getOrgIdList()); + } else { + sysRoleDataScopeService.deleteByRoleIdList(Collections.singletonList(vo.getId())); + } - // 删除用户角色关系 - sysUserRoleService.deleteByRoleIdList(idList); + // 更新角色对应用户的缓存权限 + sysUserTokenService.updateCacheAuthByRoleId(entity.getId()); + } - // 删除角色菜单关系 - sysRoleMenuService.deleteByRoleIdList(idList); + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(List idList) { + // 删除角色 + removeByIds(idList); - // 删除角色数据权限关系 - sysRoleDataScopeService.deleteByRoleIdList(idList); - } + // 删除用户角色关系 + sysUserRoleService.deleteByRoleIdList(idList); + + // 删除角色菜单关系 + sysRoleMenuService.deleteByRoleIdList(idList); + + // 删除角色数据权限关系 + sysRoleDataScopeService.deleteByRoleIdList(idList); + + // 更新角色对应用户的缓存权限 + idList.forEach(sysUserTokenService::updateCacheAuthByRoleId); + } } \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java index 0c1fa2f..a8071ac 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserDetailsServiceImpl.java @@ -2,10 +2,8 @@ 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; @@ -33,12 +31,9 @@ public class SysUserDetailsServiceImpl implements SysUserDetailsService { private final SysRoleDataScopeDao sysRoleDataScopeDao; @Override - public UserDetails getUserDetails(SysUserEntity userEntity) { - // 转换成UserDetail对象 - UserDetail userDetail = SysUserConvert.INSTANCE.convertDetail(userEntity); - + public UserDetails getUserDetails(UserDetail userDetail) { // 账号不可用 - if (userEntity.getStatus() == UserStatusEnum.DISABLE.getValue()) { + if (userDetail.getStatus() == UserStatusEnum.DISABLE.getValue()) { userDetail.setEnabled(false); } @@ -48,6 +43,11 @@ public class SysUserDetailsServiceImpl implements SysUserDetailsService { // 用户权限列表 Set authoritySet = sysMenuService.getUserAuthority(userDetail); + + // 用户角色编码列表 + List roleCodeList = sysRoleDao.geRoleCodeByUserId(userDetail.getId()); + roleCodeList.forEach(roleCode -> authoritySet.add("ROLE_" + roleCode)); + userDetail.setAuthoritySet(authoritySet); return userDetail; diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserRoleServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserRoleServiceImpl.java index 1b45bd0..026615e 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserRoleServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserRoleServiceImpl.java @@ -2,10 +2,12 @@ package net.maku.system.service.impl; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.AllArgsConstructor; import net.maku.framework.mybatis.service.impl.BaseServiceImpl; import net.maku.system.dao.SysUserRoleDao; import net.maku.system.entity.SysUserRoleEntity; import net.maku.system.service.SysUserRoleService; +import net.maku.system.service.SysUserTokenService; import org.springframework.stereotype.Service; import java.util.Collection; @@ -19,7 +21,9 @@ import java.util.stream.Collectors; * MAKU */ @Service +@AllArgsConstructor public class SysUserRoleServiceImpl extends BaseServiceImpl implements SysUserRoleService { + private final SysUserTokenService sysUserTokenService; @Override public void saveOrUpdate(Long userId, List roleIdList) { @@ -28,7 +32,7 @@ public class SysUserRoleServiceImpl extends BaseServiceImpl insertRoleIdList = CollUtil.subtract(roleIdList, dbRoleIdList); - if (CollUtil.isNotEmpty(insertRoleIdList)){ + if (CollUtil.isNotEmpty(insertRoleIdList)) { List roleList = insertRoleIdList.stream().map(roleId -> { SysUserRoleEntity entity = new SysUserRoleEntity(); entity.setUserId(userId); @@ -42,7 +46,7 @@ public class SysUserRoleServiceImpl extends BaseServiceImpl deleteRoleIdList = CollUtil.subtract(dbRoleIdList, roleIdList); - if (CollUtil.isNotEmpty(deleteRoleIdList)){ + if (CollUtil.isNotEmpty(deleteRoleIdList)) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); remove(queryWrapper.eq(SysUserRoleEntity::getUserId, userId).in(SysUserRoleEntity::getRoleId, deleteRoleIdList)); } @@ -59,6 +63,9 @@ public class SysUserRoleServiceImpl extends BaseServiceImpl userIdList) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); remove(queryWrapper.eq(SysUserRoleEntity::getRoleId, roleId).in(SysUserRoleEntity::getUserId, userIdList)); + + // 更新用户的缓存权限 + userIdList.forEach(sysUserTokenService::updateCacheAuthByUserId); } @Override diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java index c0769bb..3a93cba 100644 --- a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysUserServiceImpl.java @@ -8,10 +8,10 @@ import lombok.SneakyThrows; import net.maku.framework.common.constant.Constant; import net.maku.framework.common.excel.ExcelFinishCallBack; import net.maku.framework.common.exception.ServerException; -import net.maku.framework.common.utils.PageResult; -import net.maku.framework.mybatis.service.impl.BaseServiceImpl; import net.maku.framework.common.utils.DateUtils; import net.maku.framework.common.utils.ExcelUtils; +import net.maku.framework.common.utils.PageResult; +import net.maku.framework.mybatis.service.impl.BaseServiceImpl; import net.maku.system.convert.SysUserConvert; import net.maku.system.dao.SysUserDao; import net.maku.system.entity.SysUserEntity; @@ -21,6 +21,7 @@ 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.service.SysUserTokenService; import net.maku.system.vo.SysUserExcelVO; import net.maku.system.vo.SysUserVO; import org.springframework.stereotype.Service; @@ -43,6 +44,7 @@ import java.util.Map; public class SysUserServiceImpl extends BaseServiceImpl implements SysUserService { private final SysUserRoleService sysUserRoleService; private final SysUserPostService sysUserPostService; + private final SysUserTokenService sysUserTokenService; private final TransService transService; @Override @@ -125,6 +127,9 @@ public class SysUserServiceImpl extends BaseServiceImpl implements SysUserTokenService { + private final TokenStoreCache tokenStoreCache; + private final SysUserDetailsService sysUserDetailsService; + private final SecurityProperties securityProperties; + private final SysUserDao sysUserDao; + + @Override + public SysUserTokenVO createToken(Long userId) { + // 生成token + String accessToken = TokenUtils.generator(); + String refreshToken = TokenUtils.generator(); + + SysUserTokenEntity entity = new SysUserTokenEntity(); + entity.setUserId(userId); + entity.setAccessToken(accessToken); + entity.setRefreshToken(refreshToken); + + // 过期时间 + Date now = new Date(); + entity.setAccessTokenExpire(DateUtil.offsetSecond(now, securityProperties.getAccessTokenExpire())); + entity.setRefreshTokenExpire(DateUtil.offsetSecond(now, securityProperties.getRefreshTokenExpire())); + + // 是否存在Token + SysUserTokenEntity tokenEntity = baseMapper.selectOne(new LambdaQueryWrapper().eq(SysUserTokenEntity::getUserId, userId)); + if (tokenEntity == null) { + baseMapper.insert(entity); + } else { + entity.setId(tokenEntity.getId()); + baseMapper.updateById(entity); + } + + return SysUserTokenConvert.INSTANCE.convert(entity); + } + + @Override + public SysUserTokenVO refreshToken(String refreshToken) { + LambdaQueryWrapper query = Wrappers.lambdaQuery(); + query.eq(SysUserTokenEntity::getRefreshToken, refreshToken); + query.ge(SysUserTokenEntity::getRefreshTokenExpire, new Date()); + + // 不存在,则表示refreshToken错误,或者已过期 + SysUserTokenEntity entity = baseMapper.selectOne(query); + if (entity == null) { + throw new ServerException(ErrorCode.REFRESH_TOKEN_INVALID); + } + + // 删除缓存信息 + tokenStoreCache.deleteUser(entity.getAccessToken()); + + // 生成新 accessToken + String accessToken = TokenUtils.generator(); + entity.setAccessToken(accessToken); + entity.setAccessTokenExpire(DateUtil.offsetSecond(new Date(), securityProperties.getAccessTokenExpire())); + + // 更新 + baseMapper.updateById(entity); + + // 设置用户权限信息 + SysUserEntity user = sysUserDao.selectById(entity.getUserId()); + UserDetail userDetail = SysUserConvert.INSTANCE.convertDetail(user); + sysUserDetailsService.getUserDetails(userDetail); + + // 保存用户信息到缓存 + tokenStoreCache.saveUser(accessToken, userDetail); + + return SysUserTokenConvert.INSTANCE.convert(entity); + } + + @Override + public void expireToken(Long userId) { + SysUserTokenEntity entity = new SysUserTokenEntity(); + entity.setAccessTokenExpire(new Date()); + entity.setRefreshTokenExpire(new Date()); + + baseMapper.update(entity, new LambdaQueryWrapper().eq(SysUserTokenEntity::getUserId, userId)); + } + + @Async + @Override + public void updateCacheAuthByRoleId(Long roleId) { + // 根据角色ID,查询用户 access_token 列表 + List accessTokenList = baseMapper.getOnlineAccessTokenListByRoleId(roleId, new Date()); + + accessTokenList.forEach(this::updateCacheAuth); + } + + @Async + @Override + public void updateCacheAuthByUserId(Long userId) { + // 根据用户ID,查询用户 access_token 列表 + List accessTokenList = baseMapper.getOnlineAccessTokenListByUserId(userId, new Date()); + + accessTokenList.forEach(this::updateCacheAuth); + } + + /** + * 根据accessToken,更新Cache里面的用户权限 + * + * @param accessToken access_token + */ + private void updateCacheAuth(String accessToken) { + UserDetail user = tokenStoreCache.getUser(accessToken); + // 用户不存在 + if (user == null) { + return; + } + + // 查询过期时间 + Long expire = tokenStoreCache.getExpire(accessToken); + if (expire == null) { + return; + } + + // 设置用户权限信息 + sysUserDetailsService.getUserDetails(user); + // 更新缓存 + tokenStoreCache.saveUser(accessToken, user, expire); + + } +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/vo/AccessTokenVO.java b/maku-boot-system/src/main/java/net/maku/system/vo/AccessTokenVO.java new file mode 100644 index 0000000..3c3f027 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/vo/AccessTokenVO.java @@ -0,0 +1,33 @@ +package net.maku.system.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.maku.framework.common.utils.DateUtils; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * AccessToken + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Data +@Schema(description = "AccessToken") +public class AccessTokenVO implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + @Schema(description = "access_token") + @JsonProperty(value = "access_token") + private String accessToken; + + @Schema(description = "access_token 过期时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date accessTokenExpire; + +} diff --git a/maku-boot-system/src/main/java/net/maku/system/vo/SysUserTokenVO.java b/maku-boot-system/src/main/java/net/maku/system/vo/SysUserTokenVO.java new file mode 100644 index 0000000..a312c7d --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/vo/SysUserTokenVO.java @@ -0,0 +1,40 @@ +package net.maku.system.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.maku.framework.common.utils.DateUtils; + +import java.io.Serializable; +import java.util.Date; + +/** + * 用户Token + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Data +@AllArgsConstructor +@Schema(description = "用户Token") +public class SysUserTokenVO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "access_token") + @JsonProperty(value = "access_token") + private String accessToken; + + @Schema(description = "refresh_token") + @JsonProperty(value = "refresh_token") + private String refreshToken; + + @Schema(description = "access_token 过期时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date accessTokenExpire; + + @Schema(description = "refresh_token 过期时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date refreshTokenExpire; +} diff --git a/maku-boot-system/src/main/resources/mapper/SysUseTokenDao.xml b/maku-boot-system/src/main/resources/mapper/SysUseTokenDao.xml new file mode 100644 index 0000000..d9907bb --- /dev/null +++ b/maku-boot-system/src/main/resources/mapper/SysUseTokenDao.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file