Commit ab94fe2d4b1ec7593b684056d33efd83b2a08258
1 parent
b557251b
将 LoginUser 重构到 UserSessionService 模块汇总
Showing
20 changed files
with
283 additions
and
328 deletions
pom.xml
| ... | ... | @@ -53,7 +53,6 @@ |
| 53 | 53 | <!-- 工具类相关 --> |
| 54 | 54 | <lombok.version>1.16.14</lombok.version> |
| 55 | 55 | <mapstruct.version>1.4.1.Final</mapstruct.version> |
| 56 | - <jjwt.version>0.9.1</jjwt.version> | |
| 57 | 56 | <hutool.version>5.5.6</hutool.version> |
| 58 | 57 | <easyexcel.verion>2.2.7</easyexcel.verion> |
| 59 | 58 | </properties> |
| ... | ... | @@ -178,12 +177,6 @@ |
| 178 | 177 | </dependency> |
| 179 | 178 | |
| 180 | 179 | <dependency> |
| 181 | - <groupId>io.jsonwebtoken</groupId> | |
| 182 | - <artifactId>jjwt</artifactId> | |
| 183 | - <version>${jjwt.version}</version> | |
| 184 | - </dependency> | |
| 185 | - | |
| 186 | - <dependency> | |
| 187 | 180 | <groupId>org.projectlombok</groupId> |
| 188 | 181 | <artifactId>lombok</artifactId> |
| 189 | 182 | <version>${lombok.version}</version> | ... | ... |
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java deleted
| 1 | -package com.ruoyi; | |
| 2 | - | |
| 3 | -import org.springframework.boot.SpringApplication; | |
| 4 | -import org.springframework.boot.autoconfigure.SpringBootApplication; | |
| 5 | -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; | |
| 6 | - | |
| 7 | -/** | |
| 8 | - * 启动程序 | |
| 9 | - * | |
| 10 | - * @author ruoyi | |
| 11 | - */ | |
| 12 | -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) | |
| 13 | -public class RuoYiApplication | |
| 14 | -{ | |
| 15 | - public static void main(String[] args) | |
| 16 | - { | |
| 17 | - // System.setProperty("spring.devtools.restart.enabled", "false"); | |
| 18 | - SpringApplication.run(RuoYiApplication.class, args); | |
| 19 | - System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + | |
| 20 | - " .-------. ____ __ \n" + | |
| 21 | - " | _ _ \\ \\ \\ / / \n" + | |
| 22 | - " | ( ' ) | \\ _. / ' \n" + | |
| 23 | - " |(_ o _) / _( )_ .' \n" + | |
| 24 | - " | (_,_).' __ ___(_ o _)' \n" + | |
| 25 | - " | |\\ \\ | || |(_,_)' \n" + | |
| 26 | - " | | \\ `' /| `-' / \n" + | |
| 27 | - " | | \\ / \\ / \n" + | |
| 28 | - " ''-' `'-' `-..-' "); | |
| 29 | - } | |
| 30 | -} |
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java deleted
| 1 | -package com.ruoyi.web.controller.monitor; | |
| 2 | - | |
| 3 | -import java.util.ArrayList; | |
| 4 | -import java.util.Collection; | |
| 5 | -import java.util.Collections; | |
| 6 | -import java.util.List; | |
| 7 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 8 | -import org.springframework.security.access.prepost.PreAuthorize; | |
| 9 | -import org.springframework.web.bind.annotation.DeleteMapping; | |
| 10 | -import org.springframework.web.bind.annotation.GetMapping; | |
| 11 | -import org.springframework.web.bind.annotation.PathVariable; | |
| 12 | -import org.springframework.web.bind.annotation.RequestMapping; | |
| 13 | -import org.springframework.web.bind.annotation.RestController; | |
| 14 | -import com.ruoyi.common.annotation.Log; | |
| 15 | -import com.ruoyi.common.constant.Constants; | |
| 16 | -import com.ruoyi.common.core.controller.BaseController; | |
| 17 | -import com.ruoyi.common.core.domain.AjaxResult; | |
| 18 | -import com.ruoyi.common.core.domain.model.LoginUser; | |
| 19 | -import com.ruoyi.common.core.page.TableDataInfo; | |
| 20 | -import com.ruoyi.common.core.redis.RedisCache; | |
| 21 | -import com.ruoyi.common.enums.BusinessType; | |
| 22 | -import com.ruoyi.common.utils.StringUtils; | |
| 23 | -import com.ruoyi.system.domain.SysUserOnline; | |
| 24 | -import com.ruoyi.system.service.ISysUserOnlineService; | |
| 25 | - | |
| 26 | -/** | |
| 27 | - * 在线用户监控 | |
| 28 | - * | |
| 29 | - * @author ruoyi | |
| 30 | - */ | |
| 31 | -@RestController | |
| 32 | -@RequestMapping("/monitor/online") | |
| 33 | -public class SysUserOnlineController extends BaseController | |
| 34 | -{ | |
| 35 | - @Autowired | |
| 36 | - private ISysUserOnlineService userOnlineService; | |
| 37 | - | |
| 38 | - @Autowired | |
| 39 | - private RedisCache redisCache; | |
| 40 | - | |
| 41 | - @PreAuthorize("@ss.hasPermi('monitor:online:list')") | |
| 42 | - @GetMapping("/list") | |
| 43 | - public TableDataInfo list(String ipaddr, String userName) | |
| 44 | - { | |
| 45 | - Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*"); | |
| 46 | - List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>(); | |
| 47 | - for (String key : keys) | |
| 48 | - { | |
| 49 | - LoginUser user = redisCache.getCacheObject(key); | |
| 50 | - if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) | |
| 51 | - { | |
| 52 | - if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) | |
| 53 | - { | |
| 54 | - userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); | |
| 55 | - } | |
| 56 | - } | |
| 57 | - else if (StringUtils.isNotEmpty(ipaddr)) | |
| 58 | - { | |
| 59 | - if (StringUtils.equals(ipaddr, user.getIpaddr())) | |
| 60 | - { | |
| 61 | - userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); | |
| 62 | - } | |
| 63 | - } | |
| 64 | - else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) | |
| 65 | - { | |
| 66 | - if (StringUtils.equals(userName, user.getUsername())) | |
| 67 | - { | |
| 68 | - userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); | |
| 69 | - } | |
| 70 | - } | |
| 71 | - else | |
| 72 | - { | |
| 73 | - userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); | |
| 74 | - } | |
| 75 | - } | |
| 76 | - Collections.reverse(userOnlineList); | |
| 77 | - userOnlineList.removeAll(Collections.singleton(null)); | |
| 78 | - return getDataTable(userOnlineList); | |
| 79 | - } | |
| 80 | - | |
| 81 | - /** | |
| 82 | - * 强退用户 | |
| 83 | - */ | |
| 84 | - @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") | |
| 85 | - @Log(title = "在线用户", businessType = BusinessType.FORCE) | |
| 86 | - @DeleteMapping("/{tokenId}") | |
| 87 | - public AjaxResult forceLogout(@PathVariable String tokenId) | |
| 88 | - { | |
| 89 | - redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId); | |
| 90 | - return AjaxResult.success(); | |
| 91 | - } | |
| 92 | -} |
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties deleted
ruoyi-admin/src/main/resources/application.yml
| ... | ... | @@ -34,20 +34,6 @@ logging: |
| 34 | 34 | com.ruoyi: debug |
| 35 | 35 | org.springframework: warn |
| 36 | 36 | |
| 37 | -# Spring配置 | |
| 38 | -spring: | |
| 39 | - # 资源信息 | |
| 40 | - messages: | |
| 41 | - # 国际化资源文件路径 | |
| 42 | - basename: i18n/messages | |
| 43 | - profiles: | |
| 44 | - active: druid | |
| 45 | - # 服务模块 | |
| 46 | - devtools: | |
| 47 | - restart: | |
| 48 | - # 热部署开关 | |
| 49 | - enabled: true | |
| 50 | - | |
| 51 | 37 | # 防止XSS攻击 |
| 52 | 38 | xss: |
| 53 | 39 | # 过滤开关 | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/mybatis/core/dataobject/BaseDO.java
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java
| ... | ... | @@ -28,6 +28,8 @@ import java.util.List; |
| 28 | 28 | import static cn.iocoder.dashboard.common.pojo.CommonResult.success; |
| 29 | 29 | import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId; |
| 30 | 30 | import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds; |
| 31 | +import static cn.iocoder.dashboard.util.servlet.ServletUtils.getClientIP; | |
| 32 | +import static cn.iocoder.dashboard.util.servlet.ServletUtils.getUserAgent; | |
| 31 | 33 | |
| 32 | 34 | @Api("认证 API") |
| 33 | 35 | @RestController |
| ... | ... | @@ -47,7 +49,7 @@ public class SysAuthController { |
| 47 | 49 | @PostMapping("/login") |
| 48 | 50 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 |
| 49 | 51 | public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { |
| 50 | - String token = authService.login(reqVO.getUsername(), reqVO.getPassword(), reqVO.getUuid(), reqVO.getCode()); | |
| 52 | + String token = authService.login(reqVO, getClientIP(), getUserAgent()); | |
| 51 | 53 | // 返回结果 |
| 52 | 54 | return success(SysAuthLoginRespVO.builder().token(token).build()); |
| 53 | 55 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.auth; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.dashboard.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; | |
| 6 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; | |
| 7 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; | |
| 8 | +import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; | |
| 9 | +import io.swagger.annotations.Api; | |
| 10 | +import io.swagger.annotations.ApiImplicitParam; | |
| 11 | +import io.swagger.annotations.ApiOperation; | |
| 12 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 13 | +import org.springframework.validation.annotation.Validated; | |
| 14 | +import org.springframework.web.bind.annotation.*; | |
| 15 | + | |
| 16 | +import javax.annotation.Resource; | |
| 17 | + | |
| 18 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | |
| 19 | + | |
| 20 | +@Api("用户 Session API") | |
| 21 | +@RestController | |
| 22 | +@RequestMapping("/user-session") | |
| 23 | +public class SysUserSessionController { | |
| 24 | + | |
| 25 | + @Resource | |
| 26 | + private SysUserSessionService userSessionService; | |
| 27 | + | |
| 28 | + @ApiOperation("获得 Session 分页列表") | |
| 29 | + @PreAuthorize("@ss.hasPermission('system:user-session:page')") | |
| 30 | + @GetMapping("/page") | |
| 31 | + public CommonResult<PageResult<SysUserSessionPageItemRespVO>> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) { | |
| 32 | + // 获得 Session 分页 | |
| 33 | + PageResult<SysUserSessionDO> sessionPage = userSessionService.getUserSessionPage(reqVO); | |
| 34 | + | |
| 35 | + // | |
| 36 | + return null; | |
| 37 | + } | |
| 38 | + | |
| 39 | + @ApiOperation("删除 Session") | |
| 40 | + @PreAuthorize("@ss.hasPermission('system:user-session:delete')") | |
| 41 | + @DeleteMapping("/delete") | |
| 42 | + @ApiImplicitParam(name = "id", value = "Session 编号", required = true, dataTypeClass = String.class, | |
| 43 | + example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7") | |
| 44 | + public CommonResult<Boolean> delete(@RequestParam("id") String id) { | |
| 45 | + userSessionService.deleteUserSession(id); | |
| 46 | + return success(true); | |
| 47 | + } | |
| 48 | + | |
| 49 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.auth.vo.session; | |
| 2 | + | |
| 3 | +import cn.iocoder.dashboard.common.pojo.PageParam; | |
| 4 | +import io.swagger.annotations.ApiModel; | |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 6 | +import lombok.AllArgsConstructor; | |
| 7 | +import lombok.Data; | |
| 8 | +import lombok.EqualsAndHashCode; | |
| 9 | +import lombok.NoArgsConstructor; | |
| 10 | + | |
| 11 | +@ApiModel(value = "用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息") | |
| 12 | +@Data | |
| 13 | +@NoArgsConstructor | |
| 14 | +@AllArgsConstructor | |
| 15 | +@EqualsAndHashCode(callSuper = true) | |
| 16 | +public class SysUserSessionPageItemRespVO extends PageParam { | |
| 17 | + | |
| 18 | + @ApiModelProperty(value = "Session 编号", required = true, example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7") | |
| 19 | + private String id; | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") | |
| 22 | + private String userIp; | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") | |
| 25 | + private String userAgent; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "登陆时间", required = true) | |
| 28 | + private String createTime; | |
| 29 | + | |
| 30 | + @ApiModelProperty(value = "用户账号", required = true, example = "yudao") | |
| 31 | + private String username; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "部门名称", example = "研发部") | |
| 34 | + private String deptName; | |
| 35 | + | |
| 36 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/session/SysUserSessionPageReqVO.java
| ... | ... | @@ -2,11 +2,22 @@ package cn.iocoder.dashboard.modules.system.controller.auth.vo.session; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.PageParam; |
| 4 | 4 | import io.swagger.annotations.ApiModel; |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | 6 | import lombok.Data; |
| 6 | 7 | import lombok.EqualsAndHashCode; |
| 7 | 8 | |
| 9 | +import javax.validation.constraints.NotEmpty; | |
| 10 | + | |
| 8 | 11 | @ApiModel("在线用户 Session 分页 Request VO") |
| 9 | 12 | @Data |
| 10 | 13 | @EqualsAndHashCode(callSuper = true) |
| 11 | 14 | public class SysUserSessionPageReqVO extends PageParam { |
| 15 | + | |
| 16 | + @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配") | |
| 17 | + @NotEmpty(message = "用户 IP 不能为空") | |
| 18 | + private String userIp; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") | |
| 21 | + private String username; | |
| 22 | + | |
| 12 | 23 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/auth/SysUserOnlineMapper.java renamed to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/auth/SysUserSessionMapper.java
| ... | ... | @@ -2,6 +2,8 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; |
| 4 | 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| 5 | +import org.apache.ibatis.annotations.Mapper; | |
| 5 | 6 | |
| 6 | -public interface SysUserOnlineMapper extends BaseMapper<SysUserSessionDO> { | |
| 7 | +@Mapper | |
| 8 | +public interface SysUserSessionMapper extends BaseMapper<SysUserSessionDO> { | |
| 7 | 9 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/auth/SysUserSessionDO.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 4 | 5 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 5 | 6 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
| 8 | +import lombok.Builder; | |
| 7 | 9 | import lombok.Data; |
| 8 | 10 | import lombok.EqualsAndHashCode; |
| 9 | 11 | |
| 10 | 12 | /** |
| 11 | 13 | * 在线用户表 |
| 14 | + * | |
| 15 | + * 我们已经将 {@link LoginUser} 缓存在 Redis 当中。 | |
| 16 | + * 这里额外存储在线用户到 MySQL 中,目的是为了方便管理界面可以灵活查询。 | |
| 17 | + * 同时,通过定时轮询 SysUserSessionDO 表,可以主动删除 Redis 的缓存,因为 Redis 的过期删除是延迟的。 | |
| 18 | + * | |
| 19 | + * @author 芋道源码 | |
| 12 | 20 | */ |
| 13 | 21 | @TableName(value = "sys_user_session", autoResultMap = true) |
| 14 | 22 | @Data |
| 23 | +@Builder | |
| 15 | 24 | @EqualsAndHashCode(callSuper = true) |
| 16 | 25 | public class SysUserSessionDO extends BaseDO { |
| 17 | 26 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.service.auth; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService; |
| 4 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; | |
| 4 | 5 | |
| 5 | 6 | /** |
| 6 | 7 | * 认证 Service 接口 |
| ... | ... | @@ -11,6 +12,14 @@ import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFramewor |
| 11 | 12 | */ |
| 12 | 13 | public interface SysAuthService extends SecurityAuthFrameworkService { |
| 13 | 14 | |
| 14 | - String login(String username, String password, String captchaUUID, String captchaCode); | |
| 15 | + /** | |
| 16 | + * 登陆用户 | |
| 17 | + * | |
| 18 | + * @param reqVO 登陆信息 | |
| 19 | + * @param userIp 用户 IP | |
| 20 | + * @param userAgent 用户 UA | |
| 21 | + * @return 身份令牌,使用 JWT 方式 | |
| 22 | + */ | |
| 23 | + String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent); | |
| 15 | 24 | |
| 16 | 25 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysTokenService.java deleted
| 1 | -package cn.iocoder.dashboard.modules.system.service.auth; | |
| 2 | - | |
| 3 | -import io.jsonwebtoken.Claims; | |
| 4 | - | |
| 5 | -import java.util.Map; | |
| 6 | - | |
| 7 | -/** | |
| 8 | - * Token Service 接口 | |
| 9 | - * | |
| 10 | - * 提供访问 Token 令牌,目前基于 JWT 实现 | |
| 11 | - */ | |
| 12 | -public interface SysTokenService { | |
| 13 | - | |
| 14 | - /** | |
| 15 | - * 创建 Token | |
| 16 | - * | |
| 17 | - * @param subject 主体 | |
| 18 | - * @return Token 字符串 | |
| 19 | - */ | |
| 20 | - String createToken(String subject); | |
| 21 | - | |
| 22 | - /** | |
| 23 | - * 解析 Token,返回 claims 数据声明 | |
| 24 | - * | |
| 25 | - * @param token Token | |
| 26 | - * @return claims | |
| 27 | - */ | |
| 28 | - Claims parseToken(String token); | |
| 29 | - | |
| 30 | -} |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserOnlineService.java renamed to src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.service.auth; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 4 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 4 | 5 | import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; |
| 6 | 7 | |
| 7 | -import java.util.Date; | |
| 8 | - | |
| 9 | 8 | /** |
| 10 | 9 | * 在线用户 Session Service 接口 |
| 10 | + * | |
| 11 | + * @author 芋道源码 | |
| 11 | 12 | */ |
| 12 | -public interface SysUserOnlineService { | |
| 13 | +public interface SysUserSessionService { | |
| 13 | 14 | |
| 14 | 15 | /** |
| 15 | 16 | * 创建在线用户 Session |
| 16 | 17 | * |
| 17 | - * @param sessionId Session 编号 | |
| 18 | - * @param userId 用户编号 | |
| 18 | + * @param loginUser 登陆用户 | |
| 19 | 19 | * @param userIp 用户 IP |
| 20 | 20 | * @param userAgent 用户 UA |
| 21 | + * @return Session 编号 | |
| 22 | + */ | |
| 23 | + String createUserSession(LoginUser loginUser, String userIp, String userAgent); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 刷新在线用户 Session 的更新时间 | |
| 27 | + * | |
| 28 | + * @param sessionId Session 编号 | |
| 29 | + * @param loginUser 登陆用户 | |
| 30 | + */ | |
| 31 | + void refreshUserSession(String sessionId, LoginUser loginUser); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 删除在线用户 Session | |
| 35 | + * | |
| 36 | + * @param sessionId Session 编号 | |
| 21 | 37 | */ |
| 22 | - void createUserOnline(String sessionId, Long userId, String userIp, String userAgent); | |
| 38 | + void deleteUserSession(String sessionId); | |
| 23 | 39 | |
| 24 | 40 | /** |
| 25 | - * 更新在线用户 Session 的更新时间 | |
| 41 | + * 获得 Session 编号对应的在线用户 | |
| 26 | 42 | * |
| 27 | 43 | * @param sessionId Session 编号 |
| 28 | - * @param updateTime 更新时间 | |
| 44 | + * @return 在线用户 | |
| 45 | + */ | |
| 46 | + LoginUser getLoginUser(String sessionId); | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 获得 Session 超时时间,单位:毫秒 | |
| 50 | + * | |
| 51 | + * @return 超时时间 | |
| 29 | 52 | */ |
| 30 | - void updateUserOnlineUpdateTime(String sessionId, Date updateTime); | |
| 53 | + Long getSessionTimeoutMillis(); | |
| 31 | 54 | |
| 32 | 55 | /** |
| 33 | 56 | * 获得在线用户分页列表 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.service.auth.impl; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.util.IdUtil; | |
| 4 | -import cn.hutool.core.util.StrUtil; | |
| 5 | 3 | import cn.iocoder.dashboard.common.enums.CommonStatusEnum; |
| 6 | 4 | import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; |
| 7 | -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | |
| 8 | 5 | import cn.iocoder.dashboard.framework.security.core.LoginUser; |
| 9 | 6 | import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; |
| 7 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; | |
| 10 | 8 | import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; |
| 11 | 9 | import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; |
| 12 | 10 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 13 | -import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; | |
| 14 | 11 | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; |
| 15 | 12 | import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; |
| 16 | 13 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; |
| 17 | -import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; | |
| 14 | +import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; | |
| 18 | 15 | import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService; |
| 19 | 16 | import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService; |
| 20 | 17 | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; |
| 21 | 18 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; |
| 22 | -import cn.iocoder.dashboard.util.date.DateUtils; | |
| 23 | 19 | import cn.iocoder.dashboard.util.servlet.ServletUtils; |
| 24 | -import io.jsonwebtoken.Claims; | |
| 25 | -import io.jsonwebtoken.JwtException; | |
| 26 | 20 | import lombok.extern.slf4j.Slf4j; |
| 27 | 21 | import org.springframework.security.authentication.AuthenticationManager; |
| 28 | 22 | import org.springframework.security.authentication.BadCredentialsException; |
| ... | ... | @@ -37,7 +31,6 @@ import org.springframework.util.Assert; |
| 37 | 31 | |
| 38 | 32 | import javax.annotation.Resource; |
| 39 | 33 | import java.util.Collections; |
| 40 | -import java.util.Date; | |
| 41 | 34 | import java.util.Set; |
| 42 | 35 | |
| 43 | 36 | import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -53,11 +46,6 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; |
| 53 | 46 | public class SysAuthServiceImpl implements SysAuthService { |
| 54 | 47 | |
| 55 | 48 | @Resource |
| 56 | - private SecurityProperties securityProperties; | |
| 57 | - | |
| 58 | - @Resource | |
| 59 | - private SysTokenService tokenService; | |
| 60 | - @Resource | |
| 61 | 49 | private AuthenticationManager authenticationManager; |
| 62 | 50 | @Resource |
| 63 | 51 | private SysUserService userService; |
| ... | ... | @@ -67,9 +55,8 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 67 | 55 | private SysCaptchaService captchaService; |
| 68 | 56 | @Resource |
| 69 | 57 | private SysLoginLogService loginLogService; |
| 70 | - | |
| 71 | 58 | @Resource |
| 72 | - private SysLoginUserRedisDAO loginUserRedisDAO; | |
| 59 | + private SysUserSessionService userSessionService; | |
| 73 | 60 | |
| 74 | 61 | @Override |
| 75 | 62 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { |
| ... | ... | @@ -91,27 +78,21 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 91 | 78 | } |
| 92 | 79 | // 创建 LoginUser 对象 |
| 93 | 80 | LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); |
| 94 | - loginUser.setUpdateTime(new Date()); | |
| 95 | - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); | |
| 81 | + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 | |
| 96 | 82 | return loginUser; |
| 97 | 83 | } |
| 98 | 84 | |
| 99 | 85 | @Override |
| 100 | - public String login(String username, String password, String captchaUUID, String captchaCode) { | |
| 86 | + public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) { | |
| 101 | 87 | // 判断验证码是否正确 |
| 102 | - this.verifyCaptcha(username, captchaUUID, captchaCode); | |
| 88 | + this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode()); | |
| 103 | 89 | |
| 104 | 90 | // 使用账号密码,进行登陆。 |
| 105 | - LoginUser loginUser = this.login0(username, password); | |
| 106 | - // 缓存登陆用户到 Redis 中 | |
| 107 | - String sessionId = IdUtil.fastSimpleUUID(); | |
| 108 | - loginUser.setUpdateTime(new Date()); | |
| 109 | - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); | |
| 110 | - loginUserRedisDAO.set(sessionId, loginUser); | |
| 91 | + LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); | |
| 92 | + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 | |
| 111 | 93 | |
| 112 | - // 创建 Token | |
| 113 | - // 我们在返回给前端的 JWT 中,使用 sessionId 作为 subject 主体,标识当前 User 用户 | |
| 114 | - return tokenService.createToken(sessionId); | |
| 94 | + // 缓存登陆用户到 Redis 中,返回 sessionId 编号 | |
| 95 | + return userSessionService.createUserSession(loginUser, userIp, userAgent); | |
| 115 | 96 | } |
| 116 | 97 | |
| 117 | 98 | private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { |
| ... | ... | @@ -182,42 +163,20 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 182 | 163 | |
| 183 | 164 | @Override |
| 184 | 165 | public LoginUser verifyTokenAndRefresh(String token) { |
| 185 | - // 验证 token 的有效性 | |
| 186 | - String sessionId = this.verifyToken(token); | |
| 187 | 166 | // 获得 LoginUser |
| 188 | - LoginUser loginUser = loginUserRedisDAO.get(sessionId); | |
| 167 | + LoginUser loginUser = userSessionService.getLoginUser(token); | |
| 189 | 168 | if (loginUser == null) { |
| 190 | 169 | return null; |
| 191 | 170 | } |
| 192 | 171 | // 刷新 LoginUser 缓存 |
| 193 | - this.refreshLoginUserCache(sessionId, loginUser); | |
| 172 | + this.refreshLoginUserCache(token, loginUser); | |
| 194 | 173 | return loginUser; |
| 195 | 174 | } |
| 196 | 175 | |
| 197 | - private String verifyToken(String token) { | |
| 198 | - Claims claims; | |
| 199 | - try { | |
| 200 | - claims = tokenService.parseToken(token); | |
| 201 | - } catch (JwtException jwtException) { | |
| 202 | - log.warn("[verifyToken][token({}) 解析发生异常]", token); | |
| 203 | - return null; | |
| 204 | - } | |
| 205 | - // token 已经过期 | |
| 206 | - if (DateUtils.isExpired(claims.getExpiration())) { | |
| 207 | - return null; | |
| 208 | - } | |
| 209 | - // 判断 sessionId 是否存在 | |
| 210 | - String sessionId = claims.getSubject(); | |
| 211 | - if (StrUtil.isBlank(sessionId)) { | |
| 212 | - return null; | |
| 213 | - } | |
| 214 | - return sessionId; | |
| 215 | - } | |
| 216 | - | |
| 217 | - private void refreshLoginUserCache(String sessionId, LoginUser loginUser) { | |
| 176 | + private void refreshLoginUserCache(String token, LoginUser loginUser) { | |
| 218 | 177 | // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存 |
| 219 | 178 | if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() < |
| 220 | - securityProperties.getSessionTimeout().toMillis() / 3) { | |
| 179 | + userSessionService.getSessionTimeoutMillis() / 3) { | |
| 221 | 180 | return; |
| 222 | 181 | } |
| 223 | 182 | |
| ... | ... | @@ -229,9 +188,8 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 229 | 188 | |
| 230 | 189 | // 刷新 LoginUser 缓存 |
| 231 | 190 | loginUser.setDeptId(user.getDeptId()); |
| 232 | - loginUser.setUpdateTime(new Date()); | |
| 233 | 191 | loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); |
| 234 | - loginUserRedisDAO.set(sessionId, loginUser); | |
| 192 | + userSessionService.refreshUserSession(token, loginUser); | |
| 235 | 193 | } |
| 236 | 194 | |
| 237 | 195 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysTokenServiceImpl.java deleted
| 1 | -package cn.iocoder.dashboard.modules.system.service.auth.impl; | |
| 2 | - | |
| 3 | -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | |
| 4 | -import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; | |
| 5 | -import cn.iocoder.dashboard.util.date.DateUtils; | |
| 6 | -import io.jsonwebtoken.Claims; | |
| 7 | -import io.jsonwebtoken.Jwts; | |
| 8 | -import io.jsonwebtoken.SignatureAlgorithm; | |
| 9 | -import org.springframework.stereotype.Service; | |
| 10 | - | |
| 11 | -import javax.annotation.Resource; | |
| 12 | -import java.util.HashMap; | |
| 13 | -import java.util.Map; | |
| 14 | - | |
| 15 | -/** | |
| 16 | - * Token Service 实现类 | |
| 17 | - * | |
| 18 | - * @author 芋道源码 | |
| 19 | - */ | |
| 20 | -@Service | |
| 21 | -public class SysTokenServiceImpl implements SysTokenService { | |
| 22 | - | |
| 23 | - @Resource | |
| 24 | - private SecurityProperties securityProperties; | |
| 25 | - | |
| 26 | - @Override | |
| 27 | - public String createToken(String subject) { | |
| 28 | - return Jwts.builder() | |
| 29 | - .signWith(SignatureAlgorithm.HS512, securityProperties.getTokenSecret()) | |
| 30 | - .setExpiration(DateUtils.addTime(securityProperties.getTokenTimeout())) | |
| 31 | - .setSubject(subject) | |
| 32 | - .compact(); | |
| 33 | - } | |
| 34 | - | |
| 35 | - @Override | |
| 36 | - public Claims parseToken(String token) { | |
| 37 | - return Jwts.parser() | |
| 38 | - .setSigningKey(securityProperties.getTokenSecret()) | |
| 39 | - .parseClaimsJws(token) | |
| 40 | - .getBody(); | |
| 41 | - } | |
| 42 | - | |
| 43 | - public static void main(String[] args) { | |
| 44 | - String secret = "abcdefghijklmnopqrstuvwxyz"; | |
| 45 | - Map<String, Object> map = new HashMap<>(); | |
| 46 | - map.put("key1", "value1"); | |
| 47 | - System.out.println(Jwts.builder() | |
| 48 | - .signWith(SignatureAlgorithm.HS512, secret) | |
| 49 | - .setClaims(map) | |
| 50 | - .compact()); | |
| 51 | - | |
| 52 | - System.out.println(Jwts.parser() | |
| 53 | - .setSigningKey(secret) | |
| 54 | - .parseClaimsJws("qyJhbGciOiJIUzUxMiJ9.eyJrZXkxIjoidmFsdWUxIn0.AHWncLRBlJkqrKaoWHZmMgbqYIT7rfLs8KCp9LuC0mdNfnx1xEMm1N9bgcD-0lc5sjySqsKiWzqJ3rpoyUSh0g") | |
| 55 | - .getBody()); | |
| 56 | - } | |
| 57 | - | |
| 58 | -} |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.auth.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.IdUtil; | |
| 4 | +import cn.iocoder.dashboard.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.dashboard.framework.security.config.SecurityProperties; | |
| 6 | +import cn.iocoder.dashboard.framework.security.core.LoginUser; | |
| 7 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; | |
| 8 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth.SysUserSessionMapper; | |
| 9 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; | |
| 10 | +import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; | |
| 11 | +import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; | |
| 12 | +import org.springframework.stereotype.Service; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | +import java.util.Date; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * 在线用户 Session Service 实现类 | |
| 19 | + * | |
| 20 | + * @author 芋道源码 | |
| 21 | + */ | |
| 22 | +@Service | |
| 23 | +public class SysUserSessionServiceImpl implements SysUserSessionService { | |
| 24 | + | |
| 25 | + @Resource | |
| 26 | + private SecurityProperties securityProperties; | |
| 27 | + | |
| 28 | + @Resource | |
| 29 | + private SysLoginUserRedisDAO loginUserRedisDAO; | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private SysUserSessionMapper userSessionMapper; | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public String createUserSession(LoginUser loginUser, String userIp, String userAgent) { | |
| 36 | + // 生成 Session 编号 | |
| 37 | + String sessionId = generateSessionId(); | |
| 38 | + // 写入 Redis 缓存 | |
| 39 | + loginUser.setUpdateTime(new Date()); | |
| 40 | + loginUserRedisDAO.set(sessionId, loginUser); | |
| 41 | + // 写入 DB 中 | |
| 42 | + SysUserSessionDO userSession = SysUserSessionDO.builder().userId(loginUser.getId()) | |
| 43 | + .userIp(userIp).userAgent(userAgent).build(); | |
| 44 | + userSessionMapper.insert(userSession); | |
| 45 | + // 返回 Session 编号 | |
| 46 | + return sessionId; | |
| 47 | + } | |
| 48 | + | |
| 49 | + @Override | |
| 50 | + public void refreshUserSession(String sessionId, LoginUser loginUser) { | |
| 51 | + // 写入 Redis 缓存 | |
| 52 | + loginUser.setUpdateTime(new Date()); | |
| 53 | + loginUserRedisDAO.set(sessionId, loginUser); | |
| 54 | + // 更新 DB 中 | |
| 55 | + SysUserSessionDO updateObj = SysUserSessionDO.builder().id(sessionId).build(); | |
| 56 | + updateObj.setUpdateTime(new Date()); | |
| 57 | + userSessionMapper.updateById(updateObj); | |
| 58 | + } | |
| 59 | + | |
| 60 | + @Override | |
| 61 | + public void deleteUserSession(String sessionId) { | |
| 62 | + | |
| 63 | + } | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public LoginUser getLoginUser(String sessionId) { | |
| 67 | + return loginUserRedisDAO.get(sessionId); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public Long getSessionTimeoutMillis() { | |
| 72 | + return securityProperties.getSessionTimeout().toMillis(); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Override | |
| 76 | + public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) { | |
| 77 | + return null; | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 生成 Session 编号,目前采用 UUID 算法 | |
| 82 | + * | |
| 83 | + * @return Session 编号 | |
| 84 | + */ | |
| 85 | + private static String generateSessionId() { | |
| 86 | + return IdUtil.fastSimpleUUID(); | |
| 87 | + } | |
| 88 | + | |
| 89 | +} | ... | ... |
src/main/resources/application.yaml
ruoyi-admin/src/main/resources/banner.txt renamed to src/main/resources/banner.txt
| 1 | -Application Version: ${ruoyi.version} | |
| 2 | -Spring Boot Version: ${spring-boot.version} | |
| 3 | -//////////////////////////////////////////////////////////////////// | |
| 4 | -// _ooOoo_ // | |
| 5 | -// o8888888o // | |
| 6 | -// 88" . "88 // | |
| 7 | -// (| ^_^ |) // | |
| 8 | -// O\ = /O // | |
| 9 | -// ____/`---'\____ // | |
| 10 | -// .' \\| |// `. // | |
| 11 | -// / \\||| : |||// \ // | |
| 12 | -// / _||||| -:- |||||- \ // | |
| 13 | -// | | \\\ - /// | | // | |
| 14 | -// | \_| ''\---/'' | | // | |
| 15 | -// \ .-\__ `-` ___/-. / // | |
| 16 | -// ___`. .' /--.--\ `. . ___ // | |
| 17 | -// ."" '< `.___\_<|>_/___.' >'"". // | |
| 18 | -// | | : `- \`.;`\ _ /`;.`/ - ` : | | // | |
| 19 | -// \ \ `-. \_ __\ /__ _/ .-` / / // | |
| 20 | -// ========`-.____`-.___\_____/___.-`____.-'======== // | |
| 21 | -// `=---=' // | |
| 22 | -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // | |
| 23 | -// 佛祖保佑 永不宕机 永无BUG // | |
| 24 | -//////////////////////////////////////////////////////////////////// | |
| 25 | 1 | \ No newline at end of file |
| 2 | +芋道源码 http://www.iocoder.cn | |
| 3 | +Application Version: ${yudao.version} | |
| 4 | +Spring Boot Version: ${spring-boot.version} | |
| 5 | +//////////////////////////////////////////////////////////////////// | |
| 6 | +// _ooOoo_ // | |
| 7 | +// o8888888o // | |
| 8 | +// 88" . "88 // | |
| 9 | +// (| ^_^ |) // | |
| 10 | +// O\ = /O // | |
| 11 | +// ____/`---'\____ // | |
| 12 | +// .' \\| |// `. // | |
| 13 | +// / \\||| : |||// \ // | |
| 14 | +// / _||||| -:- |||||- \ // | |
| 15 | +// | | \\\ - /// | | // | |
| 16 | +// | \_| ''\---/'' | | // | |
| 17 | +// \ .-\__ `-` ___/-. / // | |
| 18 | +// ___`. .' /--.--\ `. . ___ // | |
| 19 | +// ."" '< `.___\_<|>_/___.' >'"". // | |
| 20 | +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // | |
| 21 | +// \ \ `-. \_ __\ /__ _/ .-` / / // | |
| 22 | +// ========`-.____`-.___\_____/___.-`____.-'======== // | |
| 23 | +// `=---=' // | |
| 24 | +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // | |
| 25 | +// 佛祖保佑 永不宕机 永无BUG // | |
| 26 | +//////////////////////////////////////////////////////////////////// | ... | ... |