新增在线用户
This commit is contained in:
parent
319dfc2de3
commit
e235d5aa57
|
@ -0,0 +1,18 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询在线用户列表
|
||||
export function list(query) {
|
||||
return request({
|
||||
url: '/monitor/online/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 强退用户
|
||||
export function forceLogout(tokenId) {
|
||||
return request({
|
||||
url: '/monitor/online/' + tokenId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
|
@ -1,5 +1,121 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
在线用户
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="登录地址">
|
||||
<el-input
|
||||
v-model="queryParams.ipaddr"
|
||||
placeholder="请输入登录地址"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名称">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="请输入用户名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<el-table-column label="序号" type="index" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="会话编号" align="center" prop="tokenId" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="登录名称" align="center" prop="userName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="部门名称" align="center" prop="deptName" />
|
||||
<el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="登录地点" align="center" prop="loginLocation" />
|
||||
<el-table-column label="浏览器" align="center" prop="browser" />
|
||||
<el-table-column label="操作系统" align="center" prop="os" />
|
||||
<el-table-column label="登录时间" align="center" prop="loginTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.loginTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleForceLogout(scope.row)"
|
||||
v-hasPermi="['monitor:online:forceLogout']"
|
||||
>强退</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { list, forceLogout } from "@/api/monitor/online";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
ipaddr: undefined,
|
||||
userName: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询登录日志列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
list(this.queryParams).then(response => {
|
||||
this.list = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 强退按钮操作 */
|
||||
handleForceLogout(row) {
|
||||
this.$confirm('是否确认强退名称为"' + row.userName + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return forceLogout(row.tokenId);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("强退成功");
|
||||
}).catch(function() {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -197,4 +197,15 @@ public class RedisCache
|
|||
Map<String, T> map = redisTemplate.opsForHash().entries(key);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象列表
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
*/
|
||||
public Collection<String> keys(String pattern)
|
||||
{
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,26 @@ public class LoginUser implements UserDetails
|
|||
*/
|
||||
private Long expireTime;
|
||||
|
||||
/**
|
||||
* 登录IP地址
|
||||
*/
|
||||
private String ipaddr;
|
||||
|
||||
/**
|
||||
* 登录地点
|
||||
*/
|
||||
private String loginLocation;
|
||||
|
||||
/**
|
||||
* 浏览器类型
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
private String os;
|
||||
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
|
@ -130,6 +150,46 @@ public class LoginUser implements UserDetails
|
|||
this.loginTime = loginTime;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Long getExpireTime()
|
||||
{
|
||||
return expireTime;
|
||||
|
|
|
@ -9,9 +9,13 @@ import org.springframework.beans.factory.annotation.Value;
|
|||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.utils.IdUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||
import com.ruoyi.common.utils.ip.IpUtils;
|
||||
import com.ruoyi.framework.redis.RedisCache;
|
||||
import com.ruoyi.framework.security.LoginUser;
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
@ -76,6 +80,7 @@ public class TokenService
|
|||
{
|
||||
String token = IdUtils.fastUUID();
|
||||
loginUser.setToken(token);
|
||||
setUserAgent(loginUser);
|
||||
refreshToken(loginUser);
|
||||
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
|
@ -104,8 +109,7 @@ public class TokenService
|
|||
/**
|
||||
* 刷新令牌有效期
|
||||
*
|
||||
* @param token 令牌
|
||||
* @return 令牌
|
||||
* @param loginUser 登录信息
|
||||
*/
|
||||
public void refreshToken(LoginUser loginUser)
|
||||
{
|
||||
|
@ -116,6 +120,21 @@ public class TokenService
|
|||
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户代理信息
|
||||
*
|
||||
* @param loginUser 登录信息
|
||||
*/
|
||||
public void setUserAgent(LoginUser loginUser)
|
||||
{
|
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
loginUser.setIpaddr(ip);
|
||||
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
||||
loginUser.setBrowser(userAgent.getBrowser().getName());
|
||||
loginUser.setOs(userAgent.getOperatingSystem().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据声明生成令牌
|
||||
*
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package com.ruoyi.project.monitor.controller;
|
||||
|
||||
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.constant.Constants;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
||||
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.ruoyi.framework.redis.RedisCache;
|
||||
import com.ruoyi.framework.security.LoginUser;
|
||||
import com.ruoyi.framework.web.controller.BaseController;
|
||||
import com.ruoyi.framework.web.domain.AjaxResult;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.project.monitor.domain.SysUserOnline;
|
||||
import com.ruoyi.project.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.DELETE)
|
||||
@DeleteMapping("/{tokenId}")
|
||||
public AjaxResult forceLogout(@PathVariable String tokenId)
|
||||
{
|
||||
redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package com.ruoyi.project.monitor.domain;
|
||||
|
||||
/**
|
||||
* 当前在线会话
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SysUserOnline
|
||||
{
|
||||
/** 会话编号 */
|
||||
private String tokenId;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 用户名称 */
|
||||
private String userName;
|
||||
|
||||
/** 登录IP地址 */
|
||||
private String ipaddr;
|
||||
|
||||
/** 登录地址 */
|
||||
private String loginLocation;
|
||||
|
||||
/** 浏览器类型 */
|
||||
private String browser;
|
||||
|
||||
/** 操作系统 */
|
||||
private String os;
|
||||
|
||||
/** 登录时间 */
|
||||
private Long loginTime;
|
||||
|
||||
public String getTokenId()
|
||||
{
|
||||
return tokenId;
|
||||
}
|
||||
|
||||
public void setTokenId(String tokenId)
|
||||
{
|
||||
this.tokenId = tokenId;
|
||||
}
|
||||
|
||||
public String getDeptName()
|
||||
{
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName)
|
||||
{
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Long getLoginTime()
|
||||
{
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public void setLoginTime(Long loginTime)
|
||||
{
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.ruoyi.project.system.service;
|
||||
|
||||
import com.ruoyi.framework.security.LoginUser;
|
||||
import com.ruoyi.project.monitor.domain.SysUserOnline;
|
||||
|
||||
/**
|
||||
* 在线用户 服务层
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ISysUserOnlineService
|
||||
{
|
||||
/**
|
||||
* 通过登录地址查询信息
|
||||
*
|
||||
* @param ipaddr 登录地址
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
|
||||
|
||||
/**
|
||||
* 通过用户名称查询信息
|
||||
*
|
||||
* @param userName 用户名称
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
public SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
|
||||
|
||||
/**
|
||||
* 通过登录地址/用户名称查询信息
|
||||
*
|
||||
* @param ipaddr 登录地址
|
||||
* @param userName 用户名称
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
|
||||
|
||||
/**
|
||||
* 设置在线用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 在线用户
|
||||
*/
|
||||
public SysUserOnline loginUserToUserOnline(LoginUser user);
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package com.ruoyi.project.system.service.impl;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.security.LoginUser;
|
||||
import com.ruoyi.project.monitor.domain.SysUserOnline;
|
||||
import com.ruoyi.project.system.service.ISysUserOnlineService;
|
||||
|
||||
/**
|
||||
* 在线用户 服务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class SysUserOnlineServiceImpl implements ISysUserOnlineService
|
||||
{
|
||||
/**
|
||||
* 通过登录地址查询信息
|
||||
*
|
||||
* @param ipaddr 登录地址
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
@Override
|
||||
public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user)
|
||||
{
|
||||
if (StringUtils.equals(ipaddr, user.getIpaddr()))
|
||||
{
|
||||
return loginUserToUserOnline(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名称查询信息
|
||||
*
|
||||
* @param userName 用户名称
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
@Override
|
||||
public SysUserOnline selectOnlineByUserName(String userName, LoginUser user)
|
||||
{
|
||||
if (StringUtils.equals(userName, user.getUsername()))
|
||||
{
|
||||
return loginUserToUserOnline(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过登录地址/用户名称查询信息
|
||||
*
|
||||
* @param ipaddr 登录地址
|
||||
* @param userName 用户名称
|
||||
* @param user 用户信息
|
||||
* @return 在线用户信息
|
||||
*/
|
||||
@Override
|
||||
public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user)
|
||||
{
|
||||
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
|
||||
{
|
||||
return loginUserToUserOnline(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置在线用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 在线用户
|
||||
*/
|
||||
public SysUserOnline loginUserToUserOnline(LoginUser user)
|
||||
{
|
||||
if (StringUtils.isNull(user) && StringUtils.isNull(user.getUser()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SysUserOnline sysUserOnline = new SysUserOnline();
|
||||
sysUserOnline.setTokenId(user.getToken());
|
||||
sysUserOnline.setUserName(user.getUsername());
|
||||
sysUserOnline.setIpaddr(user.getIpaddr());
|
||||
sysUserOnline.setLoginLocation(user.getLoginLocation());
|
||||
sysUserOnline.setBrowser(user.getBrowser());
|
||||
sysUserOnline.setOs(user.getOs());
|
||||
sysUserOnline.setLoginTime(user.getLoginTime());
|
||||
if (StringUtils.isNotNull(user.getUser().getDept()))
|
||||
{
|
||||
sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
|
||||
}
|
||||
return sysUserOnline;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue