mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-03 03:38:43 +08:00 
			
		
		
		
	将 LoginUser 重构到 UserSessionService 模块汇总
This commit is contained in:
		
							
								
								
									
										7
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								pom.xml
									
									
									
									
									
								
							@@ -53,7 +53,6 @@
 | 
				
			|||||||
        <!-- 工具类相关 -->
 | 
					        <!-- 工具类相关 -->
 | 
				
			||||||
        <lombok.version>1.16.14</lombok.version>
 | 
					        <lombok.version>1.16.14</lombok.version>
 | 
				
			||||||
        <mapstruct.version>1.4.1.Final</mapstruct.version>
 | 
					        <mapstruct.version>1.4.1.Final</mapstruct.version>
 | 
				
			||||||
        <jjwt.version>0.9.1</jjwt.version>
 | 
					 | 
				
			||||||
        <hutool.version>5.5.6</hutool.version>
 | 
					        <hutool.version>5.5.6</hutool.version>
 | 
				
			||||||
        <easyexcel.verion>2.2.7</easyexcel.verion>
 | 
					        <easyexcel.verion>2.2.7</easyexcel.verion>
 | 
				
			||||||
    </properties>
 | 
					    </properties>
 | 
				
			||||||
@@ -177,12 +176,6 @@
 | 
				
			|||||||
            <version>${lombok.version}</version>
 | 
					            <version>${lombok.version}</version>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <dependency>
 | 
					 | 
				
			||||||
            <groupId>io.jsonwebtoken</groupId>
 | 
					 | 
				
			||||||
            <artifactId>jjwt</artifactId>
 | 
					 | 
				
			||||||
            <version>${jjwt.version}</version>
 | 
					 | 
				
			||||||
        </dependency>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>org.projectlombok</groupId>
 | 
					            <groupId>org.projectlombok</groupId>
 | 
				
			||||||
            <artifactId>lombok</artifactId>
 | 
					            <artifactId>lombok</artifactId>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
package com.ruoyi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.springframework.boot.SpringApplication;
 | 
					 | 
				
			||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
					 | 
				
			||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 启动程序
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @author ruoyi
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
 | 
					 | 
				
			||||||
public class RuoYiApplication
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public static void main(String[] args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // System.setProperty("spring.devtools.restart.enabled", "false");
 | 
					 | 
				
			||||||
        SpringApplication.run(RuoYiApplication.class, args);
 | 
					 | 
				
			||||||
        System.out.println("(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  \n" +
 | 
					 | 
				
			||||||
                " .-------.       ____     __        \n" +
 | 
					 | 
				
			||||||
                " |  _ _   \\      \\   \\   /  /    \n" +
 | 
					 | 
				
			||||||
                " | ( ' )  |       \\  _. /  '       \n" +
 | 
					 | 
				
			||||||
                " |(_ o _) /        _( )_ .'         \n" +
 | 
					 | 
				
			||||||
                " | (_,_).' __  ___(_ o _)'          \n" +
 | 
					 | 
				
			||||||
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
 | 
					 | 
				
			||||||
                " |  | \\ `'   /|   `-'  /           \n" +
 | 
					 | 
				
			||||||
                " |  |  \\    /  \\      /           \n" +
 | 
					 | 
				
			||||||
                " ''-'   `'-'    `-..-'              ");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,92 +0,0 @@
 | 
				
			|||||||
package com.ruoyi.web.controller.monitor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
import java.util.Collections;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
					 | 
				
			||||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.DeleteMapping;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.PathVariable;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RestController;
 | 
					 | 
				
			||||||
import com.ruoyi.common.annotation.Log;
 | 
					 | 
				
			||||||
import com.ruoyi.common.constant.Constants;
 | 
					 | 
				
			||||||
import com.ruoyi.common.core.controller.BaseController;
 | 
					 | 
				
			||||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
					 | 
				
			||||||
import com.ruoyi.common.core.domain.model.LoginUser;
 | 
					 | 
				
			||||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
					 | 
				
			||||||
import com.ruoyi.common.core.redis.RedisCache;
 | 
					 | 
				
			||||||
import com.ruoyi.common.enums.BusinessType;
 | 
					 | 
				
			||||||
import com.ruoyi.common.utils.StringUtils;
 | 
					 | 
				
			||||||
import com.ruoyi.system.domain.SysUserOnline;
 | 
					 | 
				
			||||||
import com.ruoyi.system.service.ISysUserOnlineService;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 在线用户监控
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @author ruoyi
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@RestController
 | 
					 | 
				
			||||||
@RequestMapping("/monitor/online")
 | 
					 | 
				
			||||||
public class SysUserOnlineController extends BaseController
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    @Autowired
 | 
					 | 
				
			||||||
    private ISysUserOnlineService userOnlineService;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Autowired
 | 
					 | 
				
			||||||
    private RedisCache redisCache;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
 | 
					 | 
				
			||||||
    @GetMapping("/list")
 | 
					 | 
				
			||||||
    public TableDataInfo list(String ipaddr, String userName)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
 | 
					 | 
				
			||||||
        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
 | 
					 | 
				
			||||||
        for (String key : keys)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            LoginUser user = redisCache.getCacheObject(key);
 | 
					 | 
				
			||||||
            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (StringUtils.isNotEmpty(ipaddr))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (StringUtils.equals(ipaddr, user.getIpaddr()))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (StringUtils.equals(userName, user.getUsername()))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Collections.reverse(userOnlineList);
 | 
					 | 
				
			||||||
        userOnlineList.removeAll(Collections.singleton(null));
 | 
					 | 
				
			||||||
        return getDataTable(userOnlineList);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 强退用户
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
 | 
					 | 
				
			||||||
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
 | 
					 | 
				
			||||||
    @DeleteMapping("/{tokenId}")
 | 
					 | 
				
			||||||
    public AjaxResult forceLogout(@PathVariable String tokenId)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
 | 
					 | 
				
			||||||
        return AjaxResult.success();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
restart.include.json=/com.alibaba.fastjson.*.jar
 | 
					 | 
				
			||||||
@@ -34,20 +34,6 @@ logging:
 | 
				
			|||||||
    com.ruoyi: debug
 | 
					    com.ruoyi: debug
 | 
				
			||||||
    org.springframework: warn
 | 
					    org.springframework: warn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Spring配置
 | 
					 | 
				
			||||||
spring:
 | 
					 | 
				
			||||||
  # 资源信息
 | 
					 | 
				
			||||||
  messages:
 | 
					 | 
				
			||||||
    # 国际化资源文件路径
 | 
					 | 
				
			||||||
    basename: i18n/messages
 | 
					 | 
				
			||||||
  profiles:
 | 
					 | 
				
			||||||
    active: druid
 | 
					 | 
				
			||||||
  # 服务模块
 | 
					 | 
				
			||||||
  devtools:
 | 
					 | 
				
			||||||
    restart:
 | 
					 | 
				
			||||||
      # 热部署开关
 | 
					 | 
				
			||||||
      enabled: true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 防止XSS攻击
 | 
					# 防止XSS攻击
 | 
				
			||||||
xss:
 | 
					xss:
 | 
				
			||||||
  # 过滤开关
 | 
					  # 过滤开关
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,4 @@ public class BaseDO implements Serializable {
 | 
				
			|||||||
    @TableLogic
 | 
					    @TableLogic
 | 
				
			||||||
    private Integer deleted;
 | 
					    private Integer deleted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//    /** 备注 */ TODO 思考下,怎么解决
 | 
					 | 
				
			||||||
//    private String remark;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,8 @@ import java.util.List;
 | 
				
			|||||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 | 
					import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 | 
				
			||||||
import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId;
 | 
					import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId;
 | 
				
			||||||
import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds;
 | 
					import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds;
 | 
				
			||||||
 | 
					import static cn.iocoder.dashboard.util.servlet.ServletUtils.getClientIP;
 | 
				
			||||||
 | 
					import static cn.iocoder.dashboard.util.servlet.ServletUtils.getUserAgent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Api("认证 API")
 | 
					@Api("认证 API")
 | 
				
			||||||
@RestController
 | 
					@RestController
 | 
				
			||||||
@@ -47,7 +49,7 @@ public class SysAuthController {
 | 
				
			|||||||
    @PostMapping("/login")
 | 
					    @PostMapping("/login")
 | 
				
			||||||
    @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
 | 
					    @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
 | 
				
			||||||
    public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
 | 
					    public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
 | 
				
			||||||
        String token = authService.login(reqVO.getUsername(), reqVO.getPassword(), reqVO.getUuid(), reqVO.getCode());
 | 
					        String token = authService.login(reqVO, getClientIP(), getUserAgent());
 | 
				
			||||||
        // 返回结果
 | 
					        // 返回结果
 | 
				
			||||||
        return success(SysAuthLoginRespVO.builder().token(token).build());
 | 
					        return success(SysAuthLoginRespVO.builder().token(token).build());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					package cn.iocoder.dashboard.modules.system.controller.auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.common.pojo.CommonResult;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.common.pojo.PageResult;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService;
 | 
				
			||||||
 | 
					import io.swagger.annotations.Api;
 | 
				
			||||||
 | 
					import io.swagger.annotations.ApiImplicitParam;
 | 
				
			||||||
 | 
					import io.swagger.annotations.ApiOperation;
 | 
				
			||||||
 | 
					import org.springframework.security.access.prepost.PreAuthorize;
 | 
				
			||||||
 | 
					import org.springframework.validation.annotation.Validated;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.Resource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Api("用户 Session API")
 | 
				
			||||||
 | 
					@RestController
 | 
				
			||||||
 | 
					@RequestMapping("/user-session")
 | 
				
			||||||
 | 
					public class SysUserSessionController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private SysUserSessionService userSessionService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiOperation("获得 Session 分页列表")
 | 
				
			||||||
 | 
					    @PreAuthorize("@ss.hasPermission('system:user-session:page')")
 | 
				
			||||||
 | 
					    @GetMapping("/page")
 | 
				
			||||||
 | 
					    public CommonResult<PageResult<SysUserSessionPageItemRespVO>> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) {
 | 
				
			||||||
 | 
					        // 获得 Session 分页
 | 
				
			||||||
 | 
					        PageResult<SysUserSessionDO> sessionPage = userSessionService.getUserSessionPage(reqVO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiOperation("删除 Session")
 | 
				
			||||||
 | 
					    @PreAuthorize("@ss.hasPermission('system:user-session:delete')")
 | 
				
			||||||
 | 
					    @DeleteMapping("/delete")
 | 
				
			||||||
 | 
					    @ApiImplicitParam(name = "id", value = "Session 编号", required = true, dataTypeClass = String.class,
 | 
				
			||||||
 | 
					            example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
 | 
				
			||||||
 | 
					    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
 | 
				
			||||||
 | 
					        userSessionService.deleteUserSession(id);
 | 
				
			||||||
 | 
					        return success(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package cn.iocoder.dashboard.modules.system.controller.auth.vo.session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.common.pojo.PageParam;
 | 
				
			||||||
 | 
					import io.swagger.annotations.ApiModel;
 | 
				
			||||||
 | 
					import io.swagger.annotations.ApiModelProperty;
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					import lombok.EqualsAndHashCode;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@ApiModel(value = "用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息")
 | 
				
			||||||
 | 
					@Data
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
 | 
					@EqualsAndHashCode(callSuper = true)
 | 
				
			||||||
 | 
					public class SysUserSessionPageItemRespVO extends PageParam {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "Session 编号", required = true, example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
 | 
				
			||||||
 | 
					    private String id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
 | 
				
			||||||
 | 
					    private String userIp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0")
 | 
				
			||||||
 | 
					    private String userAgent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "登陆时间", required = true)
 | 
				
			||||||
 | 
					    private String createTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "用户账号", required = true, example = "yudao")
 | 
				
			||||||
 | 
					    private String username;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "部门名称", example = "研发部")
 | 
				
			||||||
 | 
					    private String deptName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,11 +2,22 @@ package cn.iocoder.dashboard.modules.system.controller.auth.vo.session;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import cn.iocoder.dashboard.common.pojo.PageParam;
 | 
					import cn.iocoder.dashboard.common.pojo.PageParam;
 | 
				
			||||||
import io.swagger.annotations.ApiModel;
 | 
					import io.swagger.annotations.ApiModel;
 | 
				
			||||||
 | 
					import io.swagger.annotations.ApiModelProperty;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
import lombok.EqualsAndHashCode;
 | 
					import lombok.EqualsAndHashCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.validation.constraints.NotEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiModel("在线用户 Session 分页 Request VO")
 | 
					@ApiModel("在线用户 Session 分页 Request VO")
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
@EqualsAndHashCode(callSuper = true)
 | 
					@EqualsAndHashCode(callSuper = true)
 | 
				
			||||||
public class SysUserSessionPageReqVO extends PageParam {
 | 
					public class SysUserSessionPageReqVO extends PageParam {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配")
 | 
				
			||||||
 | 
					    @NotEmpty(message = "用户 IP 不能为空")
 | 
				
			||||||
 | 
					    private String userIp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配")
 | 
				
			||||||
 | 
					    private String username;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
				
			||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 | 
					import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 | 
				
			||||||
 | 
					import org.apache.ibatis.annotations.Mapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public interface SysUserOnlineMapper extends BaseMapper<SysUserSessionDO> {
 | 
					@Mapper
 | 
				
			||||||
 | 
					public interface SysUserSessionMapper extends BaseMapper<SysUserSessionDO> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,17 +1,26 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth;
 | 
					package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 | 
					import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.framework.security.core.LoginUser;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
 | 
				
			||||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
					import com.baomidou.mybatisplus.annotation.TableId;
 | 
				
			||||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
					import com.baomidou.mybatisplus.annotation.TableName;
 | 
				
			||||||
 | 
					import lombok.Builder;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
import lombok.EqualsAndHashCode;
 | 
					import lombok.EqualsAndHashCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 在线用户表
 | 
					 * 在线用户表
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 我们已经将 {@link LoginUser} 缓存在 Redis 当中。
 | 
				
			||||||
 | 
					 * 这里额外存储在线用户到 MySQL 中,目的是为了方便管理界面可以灵活查询。
 | 
				
			||||||
 | 
					 * 同时,通过定时轮询 SysUserSessionDO 表,可以主动删除 Redis 的缓存,因为 Redis 的过期删除是延迟的。
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author 芋道源码
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@TableName(value = "sys_user_session", autoResultMap = true)
 | 
					@TableName(value = "sys_user_session", autoResultMap = true)
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
 | 
					@Builder
 | 
				
			||||||
@EqualsAndHashCode(callSuper = true)
 | 
					@EqualsAndHashCode(callSuper = true)
 | 
				
			||||||
public class SysUserSessionDO extends BaseDO {
 | 
					public class SysUserSessionDO extends BaseDO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.service.auth;
 | 
					package cn.iocoder.dashboard.modules.system.service.auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService;
 | 
					import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 认证 Service 接口
 | 
					 * 认证 Service 接口
 | 
				
			||||||
@@ -11,6 +12,14 @@ import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFramewor
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public interface SysAuthService extends SecurityAuthFrameworkService {
 | 
					public interface SysAuthService extends SecurityAuthFrameworkService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    String login(String username, String password, String captchaUUID, String captchaCode);
 | 
					    /**
 | 
				
			||||||
 | 
					     * 登陆用户
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param reqVO 登陆信息
 | 
				
			||||||
 | 
					     * @param userIp 用户 IP
 | 
				
			||||||
 | 
					     * @param userAgent 用户 UA
 | 
				
			||||||
 | 
					     * @return 身份令牌,使用 JWT 方式
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.service.auth;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import io.jsonwebtoken.Claims;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Token Service 接口
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 提供访问 Token 令牌,目前基于 JWT 实现
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public interface SysTokenService {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 创建 Token
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param subject 主体
 | 
					 | 
				
			||||||
     * @return Token 字符串
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    String createToken(String subject);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 解析 Token,返回 claims 数据声明
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param token Token
 | 
					 | 
				
			||||||
     * @return claims
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    Claims parseToken(String token);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,40 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.service.auth;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.common.pojo.PageResult;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.Date;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 在线用户 Session Service 接口
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public interface SysUserOnlineService {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 创建在线用户 Session
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param sessionId Session 编号
 | 
					 | 
				
			||||||
     * @param userId 用户编号
 | 
					 | 
				
			||||||
     * @param userIp 用户 IP
 | 
					 | 
				
			||||||
     * @param userAgent 用户 UA
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void createUserOnline(String sessionId, Long userId, String userIp, String userAgent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 更新在线用户 Session 的更新时间
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param sessionId Session 编号
 | 
					 | 
				
			||||||
     * @param updateTime 更新时间
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void updateUserOnlineUpdateTime(String sessionId, Date updateTime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 获得在线用户分页列表
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param reqVO 分页条件
 | 
					 | 
				
			||||||
     * @return 份额与列表
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					package cn.iocoder.dashboard.modules.system.service.auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.common.pojo.PageResult;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.framework.security.core.LoginUser;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 在线用户 Session Service 接口
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author 芋道源码
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public interface SysUserSessionService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 创建在线用户 Session
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param loginUser 登陆用户
 | 
				
			||||||
 | 
					     * @param userIp 用户 IP
 | 
				
			||||||
 | 
					     * @param userAgent 用户 UA
 | 
				
			||||||
 | 
					     * @return Session 编号
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    String createUserSession(LoginUser loginUser, String userIp, String userAgent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 刷新在线用户 Session 的更新时间
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sessionId Session 编号
 | 
				
			||||||
 | 
					     * @param loginUser 登陆用户
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void refreshUserSession(String sessionId, LoginUser loginUser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 删除在线用户 Session
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sessionId Session 编号
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void deleteUserSession(String sessionId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 获得 Session 编号对应的在线用户
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sessionId Session 编号
 | 
				
			||||||
 | 
					     * @return 在线用户
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    LoginUser getLoginUser(String sessionId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 获得 Session 超时时间,单位:毫秒
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return 超时时间
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Long getSessionTimeoutMillis();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 获得在线用户分页列表
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param reqVO 分页条件
 | 
				
			||||||
 | 
					     * @return 份额与列表
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,28 +1,22 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.service.auth.impl;
 | 
					package cn.iocoder.dashboard.modules.system.service.auth.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.hutool.core.util.IdUtil;
 | 
					 | 
				
			||||||
import cn.hutool.core.util.StrUtil;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 | 
					import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 | 
				
			||||||
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
 | 
					import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
 | 
				
			||||||
import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.framework.security.core.LoginUser;
 | 
					import cn.iocoder.dashboard.framework.security.core.LoginUser;
 | 
				
			||||||
import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
 | 
					import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
 | 
					import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
 | 
					import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum;
 | 
					import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum;
 | 
					import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
 | 
					import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService;
 | 
					import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService;
 | 
					import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService;
 | 
					import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
 | 
					import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
 | 
					import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
 | 
				
			||||||
import cn.iocoder.dashboard.util.date.DateUtils;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.util.servlet.ServletUtils;
 | 
					import cn.iocoder.dashboard.util.servlet.ServletUtils;
 | 
				
			||||||
import io.jsonwebtoken.Claims;
 | 
					 | 
				
			||||||
import io.jsonwebtoken.JwtException;
 | 
					 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
import org.springframework.security.authentication.AuthenticationManager;
 | 
					import org.springframework.security.authentication.AuthenticationManager;
 | 
				
			||||||
import org.springframework.security.authentication.BadCredentialsException;
 | 
					import org.springframework.security.authentication.BadCredentialsException;
 | 
				
			||||||
@@ -37,7 +31,6 @@ import org.springframework.util.Assert;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import javax.annotation.Resource;
 | 
					import javax.annotation.Resource;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.Date;
 | 
					 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
 | 
					import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
 | 
				
			||||||
@@ -52,11 +45,6 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
 | 
				
			|||||||
@Slf4j
 | 
					@Slf4j
 | 
				
			||||||
public class SysAuthServiceImpl implements SysAuthService {
 | 
					public class SysAuthServiceImpl implements SysAuthService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private SecurityProperties securityProperties;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private SysTokenService tokenService;
 | 
					 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private AuthenticationManager authenticationManager;
 | 
					    private AuthenticationManager authenticationManager;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
@@ -67,9 +55,8 @@ public class SysAuthServiceImpl implements SysAuthService {
 | 
				
			|||||||
    private SysCaptchaService captchaService;
 | 
					    private SysCaptchaService captchaService;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private SysLoginLogService loginLogService;
 | 
					    private SysLoginLogService loginLogService;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private SysLoginUserRedisDAO loginUserRedisDAO;
 | 
					    private SysUserSessionService userSessionService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 | 
					    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 | 
				
			||||||
@@ -91,27 +78,21 @@ public class SysAuthServiceImpl implements SysAuthService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // 创建 LoginUser 对象
 | 
					        // 创建 LoginUser 对象
 | 
				
			||||||
        LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
 | 
					        LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
 | 
				
			||||||
        loginUser.setUpdateTime(new Date());
 | 
					        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 | 
				
			||||||
        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
 | 
					 | 
				
			||||||
        return loginUser;
 | 
					        return loginUser;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public String login(String username, String password, String captchaUUID, String captchaCode) {
 | 
					    public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) {
 | 
				
			||||||
        // 判断验证码是否正确
 | 
					        // 判断验证码是否正确
 | 
				
			||||||
        this.verifyCaptcha(username, captchaUUID, captchaCode);
 | 
					        this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 使用账号密码,进行登陆。
 | 
					        // 使用账号密码,进行登陆。
 | 
				
			||||||
        LoginUser loginUser = this.login0(username, password);
 | 
					        LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
 | 
				
			||||||
        // 缓存登陆用户到 Redis 中
 | 
					        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 | 
				
			||||||
        String sessionId = IdUtil.fastSimpleUUID();
 | 
					 | 
				
			||||||
        loginUser.setUpdateTime(new Date());
 | 
					 | 
				
			||||||
        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
 | 
					 | 
				
			||||||
        loginUserRedisDAO.set(sessionId, loginUser);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 创建 Token
 | 
					        // 缓存登陆用户到 Redis 中,返回 sessionId 编号
 | 
				
			||||||
        // 我们在返回给前端的 JWT 中,使用 sessionId 作为 subject 主体,标识当前 User 用户
 | 
					        return userSessionService.createUserSession(loginUser, userIp, userAgent);
 | 
				
			||||||
        return tokenService.createToken(sessionId);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
 | 
					    private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
 | 
				
			||||||
@@ -182,42 +163,20 @@ public class SysAuthServiceImpl implements SysAuthService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public LoginUser verifyTokenAndRefresh(String token) {
 | 
					    public LoginUser verifyTokenAndRefresh(String token) {
 | 
				
			||||||
        // 验证 token 的有效性
 | 
					 | 
				
			||||||
        String sessionId = this.verifyToken(token);
 | 
					 | 
				
			||||||
        // 获得 LoginUser
 | 
					        // 获得 LoginUser
 | 
				
			||||||
        LoginUser loginUser = loginUserRedisDAO.get(sessionId);
 | 
					        LoginUser loginUser = userSessionService.getLoginUser(token);
 | 
				
			||||||
        if (loginUser == null) {
 | 
					        if (loginUser == null) {
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // 刷新 LoginUser 缓存
 | 
					        // 刷新 LoginUser 缓存
 | 
				
			||||||
        this.refreshLoginUserCache(sessionId, loginUser);
 | 
					        this.refreshLoginUserCache(token, loginUser);
 | 
				
			||||||
        return loginUser;
 | 
					        return loginUser;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String verifyToken(String token) {
 | 
					    private void refreshLoginUserCache(String token, LoginUser loginUser) {
 | 
				
			||||||
        Claims claims;
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            claims = tokenService.parseToken(token);
 | 
					 | 
				
			||||||
        } catch (JwtException jwtException) {
 | 
					 | 
				
			||||||
            log.warn("[verifyToken][token({}) 解析发生异常]", token);
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // token 已经过期
 | 
					 | 
				
			||||||
        if (DateUtils.isExpired(claims.getExpiration())) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // 判断 sessionId 是否存在
 | 
					 | 
				
			||||||
        String sessionId = claims.getSubject();
 | 
					 | 
				
			||||||
        if (StrUtil.isBlank(sessionId)) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return sessionId;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void refreshLoginUserCache(String sessionId, LoginUser loginUser) {
 | 
					 | 
				
			||||||
        // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
 | 
					        // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
 | 
				
			||||||
        if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
 | 
					        if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
 | 
				
			||||||
                securityProperties.getSessionTimeout().toMillis() / 3) {
 | 
					                userSessionService.getSessionTimeoutMillis() / 3) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -229,9 +188,8 @@ public class SysAuthServiceImpl implements SysAuthService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 刷新 LoginUser 缓存
 | 
					        // 刷新 LoginUser 缓存
 | 
				
			||||||
        loginUser.setDeptId(user.getDeptId());
 | 
					        loginUser.setDeptId(user.getDeptId());
 | 
				
			||||||
        loginUser.setUpdateTime(new Date());
 | 
					 | 
				
			||||||
        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
 | 
					        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
 | 
				
			||||||
        loginUserRedisDAO.set(sessionId, loginUser);
 | 
					        userSessionService.refreshUserSession(token, loginUser);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,58 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.dashboard.modules.system.service.auth.impl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService;
 | 
					 | 
				
			||||||
import cn.iocoder.dashboard.util.date.DateUtils;
 | 
					 | 
				
			||||||
import io.jsonwebtoken.Claims;
 | 
					 | 
				
			||||||
import io.jsonwebtoken.Jwts;
 | 
					 | 
				
			||||||
import io.jsonwebtoken.SignatureAlgorithm;
 | 
					 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.annotation.Resource;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Token Service 实现类
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Service
 | 
					 | 
				
			||||||
public class SysTokenServiceImpl implements SysTokenService {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private SecurityProperties securityProperties;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String createToken(String subject) {
 | 
					 | 
				
			||||||
        return Jwts.builder()
 | 
					 | 
				
			||||||
                .signWith(SignatureAlgorithm.HS512, securityProperties.getTokenSecret())
 | 
					 | 
				
			||||||
                .setExpiration(DateUtils.addTime(securityProperties.getTokenTimeout()))
 | 
					 | 
				
			||||||
                .setSubject(subject)
 | 
					 | 
				
			||||||
                .compact();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public Claims parseToken(String token) {
 | 
					 | 
				
			||||||
        return Jwts.parser()
 | 
					 | 
				
			||||||
                .setSigningKey(securityProperties.getTokenSecret())
 | 
					 | 
				
			||||||
                .parseClaimsJws(token)
 | 
					 | 
				
			||||||
                .getBody();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static void main(String[] args) {
 | 
					 | 
				
			||||||
        String secret = "abcdefghijklmnopqrstuvwxyz";
 | 
					 | 
				
			||||||
        Map<String, Object> map = new HashMap<>();
 | 
					 | 
				
			||||||
        map.put("key1", "value1");
 | 
					 | 
				
			||||||
        System.out.println(Jwts.builder()
 | 
					 | 
				
			||||||
                .signWith(SignatureAlgorithm.HS512, secret)
 | 
					 | 
				
			||||||
                .setClaims(map)
 | 
					 | 
				
			||||||
                .compact());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        System.out.println(Jwts.parser()
 | 
					 | 
				
			||||||
                .setSigningKey(secret)
 | 
					 | 
				
			||||||
                .parseClaimsJws("qyJhbGciOiJIUzUxMiJ9.eyJrZXkxIjoidmFsdWUxIn0.AHWncLRBlJkqrKaoWHZmMgbqYIT7rfLs8KCp9LuC0mdNfnx1xEMm1N9bgcD-0lc5sjySqsKiWzqJ3rpoyUSh0g")
 | 
					 | 
				
			||||||
                .getBody());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					package cn.iocoder.dashboard.modules.system.service.auth.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.hutool.core.util.IdUtil;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.common.pojo.PageResult;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.framework.security.core.LoginUser;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth.SysUserSessionMapper;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
 | 
				
			||||||
 | 
					import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.annotation.Resource;
 | 
				
			||||||
 | 
					import java.util.Date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 在线用户 Session Service 实现类
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author 芋道源码
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Service
 | 
				
			||||||
 | 
					public class SysUserSessionServiceImpl implements SysUserSessionService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private SecurityProperties securityProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private SysLoginUserRedisDAO loginUserRedisDAO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private SysUserSessionMapper userSessionMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
 | 
				
			||||||
 | 
					        // 生成 Session 编号
 | 
				
			||||||
 | 
					        String sessionId = generateSessionId();
 | 
				
			||||||
 | 
					        // 写入 Redis 缓存
 | 
				
			||||||
 | 
					        loginUser.setUpdateTime(new Date());
 | 
				
			||||||
 | 
					        loginUserRedisDAO.set(sessionId, loginUser);
 | 
				
			||||||
 | 
					        // 写入 DB 中
 | 
				
			||||||
 | 
					        SysUserSessionDO userSession = SysUserSessionDO.builder().userId(loginUser.getId())
 | 
				
			||||||
 | 
					                .userIp(userIp).userAgent(userAgent).build();
 | 
				
			||||||
 | 
					        userSessionMapper.insert(userSession);
 | 
				
			||||||
 | 
					        // 返回 Session 编号
 | 
				
			||||||
 | 
					        return sessionId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void refreshUserSession(String sessionId, LoginUser loginUser) {
 | 
				
			||||||
 | 
					        // 写入 Redis 缓存
 | 
				
			||||||
 | 
					        loginUser.setUpdateTime(new Date());
 | 
				
			||||||
 | 
					        loginUserRedisDAO.set(sessionId, loginUser);
 | 
				
			||||||
 | 
					        // 更新 DB 中
 | 
				
			||||||
 | 
					        SysUserSessionDO updateObj = SysUserSessionDO.builder().id(sessionId).build();
 | 
				
			||||||
 | 
					        updateObj.setUpdateTime(new Date());
 | 
				
			||||||
 | 
					        userSessionMapper.updateById(updateObj);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void deleteUserSession(String sessionId) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public LoginUser getLoginUser(String sessionId) {
 | 
				
			||||||
 | 
					        return loginUserRedisDAO.get(sessionId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Long getSessionTimeoutMillis() {
 | 
				
			||||||
 | 
					        return securityProperties.getSessionTimeout().toMillis();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 生成 Session 编号,目前采用 UUID 算法
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Session 编号
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static String generateSessionId() {
 | 
				
			||||||
 | 
					        return IdUtil.fastSimpleUUID();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -41,6 +41,7 @@ spring:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# 芋道配置项,设置当前项目所有自定义的配置
 | 
					# 芋道配置项,设置当前项目所有自定义的配置
 | 
				
			||||||
yudao:
 | 
					yudao:
 | 
				
			||||||
 | 
					  version: 1.0.0
 | 
				
			||||||
  web:
 | 
					  web:
 | 
				
			||||||
    api-prefix: /api
 | 
					    api-prefix: /api
 | 
				
			||||||
    controller-package: cn.iocoder.dashboard
 | 
					    controller-package: cn.iocoder.dashboard
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
Application Version: ${ruoyi.version}
 | 
					芋道源码 http://www.iocoder.cn
 | 
				
			||||||
 | 
					Application Version: ${yudao.version}
 | 
				
			||||||
Spring Boot Version: ${spring-boot.version}
 | 
					Spring Boot Version: ${spring-boot.version}
 | 
				
			||||||
////////////////////////////////////////////////////////////////////
 | 
					////////////////////////////////////////////////////////////////////
 | 
				
			||||||
//                          _ooOoo_                               //
 | 
					//                          _ooOoo_                               //
 | 
				
			||||||
		Reference in New Issue
	
	Block a user