mirror of https://github.com/tp4a/teleport
增强:强制中断在线会话功能实现了,SSH协议已测试,RDP和TELNET协议尚未实现。
parent
685f31f566
commit
3eb59eb071
|
@ -14,6 +14,9 @@
|
|||
# define TPP_API
|
||||
#endif
|
||||
|
||||
#define TPP_CMD_INIT 0x00000000
|
||||
#define TPP_CMD_KILL_SESSIONS 0x00000006
|
||||
|
||||
typedef struct TPP_CONNECT_INFO
|
||||
{
|
||||
char* sid;
|
||||
|
@ -79,6 +82,8 @@ extern "C"
|
|||
TPP_API void tpp_timer(void);
|
||||
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args);
|
||||
|
||||
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -89,4 +94,6 @@ typedef ex_rv(*TPP_STOP_FUNC)(void);
|
|||
typedef void(*TPP_TIMER_FUNC)(void);
|
||||
typedef void(*TPP_SET_CFG_FUNC)(TPP_SET_CFG_ARGS* cfg_args);
|
||||
|
||||
typedef ex_rv(*TPP_COMMAND_FUNC)(ex_u32 cmd, const char* param); // param is a JSON formatted string.
|
||||
|
||||
#endif // __TP_PROTOCOL_INTERFACE_H__
|
||||
|
|
|
@ -47,15 +47,17 @@ bool TppManager::load_tpp(const ex_wstr& libname)
|
|||
lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
|
||||
lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
|
||||
lib->set_cfg = (TPP_SET_CFG_FUNC)GetProcAddress(lib->dylib, "tpp_set_cfg");
|
||||
lib->command = (TPP_COMMAND_FUNC)GetProcAddress(lib->dylib, "tpp_command");
|
||||
#else
|
||||
lib->init = (TPP_INIT_FUNC)dlsym(lib->dylib, "tpp_init");
|
||||
lib->start = (TPP_START_FUNC)dlsym(lib->dylib, "tpp_start");
|
||||
lib->stop = (TPP_STOP_FUNC)dlsym(lib->dylib, "tpp_stop");
|
||||
lib->timer = (TPP_TIMER_FUNC)dlsym(lib->dylib, "tpp_timer");
|
||||
lib->set_cfg = (TPP_SET_CFG_FUNC)dlsym(lib->dylib, "tpp_set_cfg");
|
||||
lib->command = (TPP_COMMAND_FUNC)dlsym(lib->dylib, "tpp_command");
|
||||
#endif
|
||||
|
||||
if (lib->init == NULL || lib->start == NULL || lib->stop == NULL || lib->timer == NULL || lib->set_cfg == NULL)
|
||||
if (lib->init == NULL || lib->start == NULL || lib->stop == NULL || lib->timer == NULL || lib->set_cfg == NULL || lib->command == NULL)
|
||||
{
|
||||
EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", libfile.c_str());
|
||||
delete lib;
|
||||
|
@ -118,3 +120,12 @@ void TppManager::set_config(int noop_timeout) {
|
|||
(*it)->set_cfg(&args);
|
||||
}
|
||||
}
|
||||
|
||||
void TppManager::kill_sessions(const ex_astr& sessions) {
|
||||
tpp_libs::iterator it = m_libs.begin();
|
||||
for (; it != m_libs.end(); ++it)
|
||||
{
|
||||
(*it)->command(TPP_CMD_KILL_SESSIONS, sessions.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ typedef struct TPP_LIB
|
|||
TPP_STOP_FUNC stop;
|
||||
TPP_TIMER_FUNC timer;
|
||||
TPP_SET_CFG_FUNC set_cfg;
|
||||
|
||||
TPP_COMMAND_FUNC command;
|
||||
}TPP_LIB;
|
||||
|
||||
typedef std::list<TPP_LIB*> tpp_libs;
|
||||
|
@ -51,6 +53,7 @@ public:
|
|||
int count(void) { return m_libs.size(); }
|
||||
|
||||
void set_config(int noop_timeout);
|
||||
void kill_sessions(const ex_astr& sessions);
|
||||
|
||||
private:
|
||||
tpp_libs m_libs;
|
||||
|
|
|
@ -255,6 +255,9 @@ void TsHttpRpc::_process_request(const ex_astr& func_cmd, const Json::Value& jso
|
|||
if (func_cmd == "request_session") {
|
||||
_rpc_func_request_session(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "kill_sessions") {
|
||||
_rpc_func_kill_sessions(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "get_config") {
|
||||
_rpc_func_get_config(json_param, buf);
|
||||
}
|
||||
|
@ -378,6 +381,45 @@ void TsHttpRpc::_rpc_func_request_session(const Json::Value& json_param, ex_astr
|
|||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf) {
|
||||
/*
|
||||
{
|
||||
"sessions": ["0123456", "ABCDEF", ...]
|
||||
}
|
||||
*/
|
||||
|
||||
if (json_param.isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (json_param["sessions"].isNull() || !json_param["sessions"].isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
Json::Value s = json_param["sessions"];
|
||||
int cnt = s.size();
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
if (!s[i].isString()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXLOGV("[core] kill %d sessions.\n", cnt);
|
||||
|
||||
ex_astr ss = s.toStyledString();
|
||||
|
||||
g_tpp_mgr.kill_sessions(ss);
|
||||
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
}
|
||||
|
||||
|
||||
void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#enc
|
||||
|
@ -428,7 +470,7 @@ void TsHttpRpc::_rpc_func_set_config(const Json::Value& json_param, ex_astr& buf
|
|||
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#set_config
|
||||
/*
|
||||
{
|
||||
"noop-timeout": 900 # 900s = 15m
|
||||
"noop-timeout": 15 # 按分钟计
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -453,7 +495,7 @@ void TsHttpRpc::_rpc_func_set_config(const Json::Value& json_param, ex_astr& buf
|
|||
|
||||
//static TppManager g_tpp_mgr;
|
||||
EXLOGV("[core] no-op timeout set to %d minutes.\n", noop_timeout);
|
||||
g_tpp_mgr.set_config(noop_timeout * 60);
|
||||
g_tpp_mgr.set_config(noop_timeout * 60); // 内部按秒计,因此要 *60
|
||||
|
||||
|
||||
// Json::Value jr_data;
|
||||
|
|
|
@ -37,6 +37,8 @@ private:
|
|||
void _rpc_func_set_config(const Json::Value& json_param, ex_astr& buf);
|
||||
// 请求一个会话ID
|
||||
void _rpc_func_request_session(const Json::Value& json_param, ex_astr& buf);
|
||||
// 强行终止会话
|
||||
void _rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf);
|
||||
// 加密一个字符串(返回的是密文的BASE64编码)
|
||||
void _rpc_func_enc(const Json::Value& json_param, ex_astr& buf);
|
||||
// 要求整个核心服务退出
|
||||
|
|
|
@ -87,6 +87,20 @@ void SshProxy::set_cfg(TPP_SET_CFG_ARGS* args) {
|
|||
m_noop_timeout_sec = args->noop_timeout;
|
||||
}
|
||||
|
||||
void SshProxy::kill_sessions(const ex_astrs& sessions) {
|
||||
ExThreadSmartLock locker(m_lock);
|
||||
ts_ssh_sessions::iterator it;
|
||||
for (it = m_sessions.begin(); it != m_sessions.end(); ++it) {
|
||||
for (size_t i = 0; i < sessions.size(); ++i) {
|
||||
if (it->first->sid() == sessions[i]) {
|
||||
EXLOGW("[ssh] try to kill %s\n", sessions[i].c_str());
|
||||
it->first->check_noop_timeout(0, 0); // Á¢¼´½áÊø
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SshProxy::_thread_loop()
|
||||
{
|
||||
EXLOGI("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
bool init();
|
||||
void timer();
|
||||
void set_cfg(TPP_SET_CFG_ARGS* args);
|
||||
void kill_sessions(const ex_astrs& sessions);
|
||||
|
||||
void session_finished(SshSession* sess);
|
||||
|
||||
|
|
|
@ -191,11 +191,14 @@ void SshSession::_check_channels() {
|
|||
|| (cli == NULL && srv != NULL && ssh_channel_is_closed(srv))
|
||||
|| (srv == NULL && cli != NULL && ssh_channel_is_closed(cli))
|
||||
) {
|
||||
if (cli)
|
||||
if (cli) {
|
||||
ssh_channel_free(cli);
|
||||
if (srv)
|
||||
cli = NULL;
|
||||
}
|
||||
if (srv) {
|
||||
ssh_channel_free(srv);
|
||||
|
||||
srv = NULL;
|
||||
}
|
||||
_record_end((*it));
|
||||
|
||||
delete(*it);
|
||||
|
@ -407,8 +410,11 @@ void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
|||
for (; it != m_channels.end(); ++it) {
|
||||
if ((*it)->need_close)
|
||||
continue;
|
||||
if (t_now - (*it)->last_access_timestamp > timeout) {
|
||||
EXLOGW("[ssh] need close channel by timeout.\n");
|
||||
if (t_now == 0)
|
||||
EXLOGW("[ssh] try close channel by kill.\n");
|
||||
else if (t_now - (*it)->last_access_timestamp > timeout)
|
||||
EXLOGW("[ssh] try close channel by timeout.\n");
|
||||
if (t_now == 0 || t_now - (*it)->last_access_timestamp > timeout) {
|
||||
(*it)->need_close = true;
|
||||
m_have_error = true;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ public:
|
|||
//
|
||||
void check_noop_timeout(ex_u32 t_now, ex_u32 timeout);
|
||||
|
||||
const ex_astr& sid() { return m_sid; }
|
||||
|
||||
protected:
|
||||
void _thread_loop(void);
|
||||
void _set_stop_flag(void);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "tpp_env.h"
|
||||
|
||||
#include <teleport_const.h>
|
||||
#include <json/json.h>
|
||||
|
||||
|
||||
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args)
|
||||
{
|
||||
|
@ -42,3 +44,45 @@ TPP_API void tpp_timer(void) {
|
|||
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args) {
|
||||
g_ssh_proxy.set_cfg(cfg_args);
|
||||
}
|
||||
|
||||
static ex_rv _kill_sessions(const char* param) {
|
||||
Json::Value jp;
|
||||
Json::Reader jreader;
|
||||
|
||||
if (!jreader.parse(param, jp))
|
||||
return TPE_JSON_FORMAT;
|
||||
|
||||
if (!jp.isArray())
|
||||
return TPE_PARAM;
|
||||
|
||||
ex_astrs ss;
|
||||
int cnt = jp.size();
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
if (!jp[i].isString()) {
|
||||
return TPE_PARAM;
|
||||
}
|
||||
|
||||
ss.push_back(jp[i].asString());
|
||||
}
|
||||
|
||||
g_ssh_proxy.kill_sessions(ss);
|
||||
|
||||
return TPE_PARAM;
|
||||
}
|
||||
|
||||
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param) {
|
||||
switch (cmd) {
|
||||
case TPP_CMD_KILL_SESSIONS:
|
||||
if (param == NULL || strlen(param) == 0)
|
||||
return TPE_PARAM;
|
||||
return _kill_sessions(param);
|
||||
default:
|
||||
return TPE_UNKNOWN_CMD;
|
||||
}
|
||||
|
||||
return TPE_NOT_IMPLEMENT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../common\teleport;../../../../common\libex\include;../../../../external/jsoncpp/include;../../../../external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -86,7 +86,7 @@
|
|||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../common\teleport;../../../../common\libex\include;../../../../external/jsoncpp/include;../../../../external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -109,6 +109,7 @@
|
|||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
|
||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
|
||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
|
||||
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h" />
|
||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
|
||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />
|
||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h" />
|
||||
|
@ -133,6 +134,9 @@
|
|||
<ClCompile Include="..\..\..\..\common\libex\src\ex_thread.cpp" />
|
||||
<ClCompile Include="..\..\..\..\common\libex\src\ex_util.cpp" />
|
||||
<ClCompile Include="..\..\..\..\common\libex\src\ex_winsrv.cpp" />
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_reader.cpp" />
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_value.cpp" />
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_writer.cpp" />
|
||||
<ClCompile Include="..\..\common\base_env.cpp" />
|
||||
<ClCompile Include="..\..\common\base_record.cpp" />
|
||||
<ClCompile Include="..\..\common\ts_membuf.cpp" />
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<Filter Include="libssh">
|
||||
<UniqueIdentifier>{f1fea9ae-123c-4aa8-a152-e88d1d0a29fd}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="jsoncpp">
|
||||
<UniqueIdentifier>{022b0a3d-47c2-40d8-96d9-dceea02e7eef}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h">
|
||||
|
@ -107,6 +110,9 @@
|
|||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h">
|
||||
<Filter>libssh</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h">
|
||||
<Filter>jsoncpp</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="tpssh.cpp">
|
||||
|
@ -160,5 +166,14 @@
|
|||
<ClCompile Include="ssh_recorder.cpp">
|
||||
<Filter>main app</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_reader.cpp">
|
||||
<Filter>jsoncpp</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_value.cpp">
|
||||
<Filter>jsoncpp</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_writer.cpp">
|
||||
<Filter>jsoncpp</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -80,7 +80,7 @@ $app.create_controls = function (cb_stack) {
|
|||
fields: {time_begin: 'time_begin'}
|
||||
},
|
||||
{
|
||||
title: '耗时',
|
||||
title: '时长',
|
||||
key: 'time_cost',
|
||||
render: 'time_cost',
|
||||
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
||||
|
|
|
@ -45,6 +45,13 @@ $app.create_controls = function (cb_stack) {
|
|||
sort_asc: false,
|
||||
fields: {id: 'id'}
|
||||
},
|
||||
{
|
||||
title: '会话ID',
|
||||
key: 'sid',
|
||||
sort: true,
|
||||
sort_asc: false,
|
||||
fields: {sid: 'sid'}
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
|
@ -90,7 +97,7 @@ $app.create_controls = function (cb_stack) {
|
|||
fields: {time_begin: 'time_begin'}
|
||||
},
|
||||
{
|
||||
title: '耗时',
|
||||
title: '时长',
|
||||
key: 'time_cost',
|
||||
render: 'time_cost',
|
||||
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
||||
|
@ -170,30 +177,22 @@ $app.create_controls = function (cb_stack) {
|
|||
$app.on_table_session_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||
if (col_key === 'chkbox') {
|
||||
cell_obj.find('[data-check-box]').click(function () {
|
||||
// 同步相同会话ID的选中状态
|
||||
var _obj = $(this);
|
||||
var checked = _obj.is(':checked');
|
||||
var _row_data = tbl.get_row(_obj);
|
||||
var _objs = $('#' + $app.table_session.dom_id + ' tbody').find('[data-check-box]');
|
||||
$.each(_objs, function (i, _o) {
|
||||
var _rd = tbl.get_row(_o);
|
||||
if (_row_data.sid === _rd.sid) {
|
||||
$(_o).prop('checked', checked);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$app.check_host_all_selected();
|
||||
});
|
||||
}
|
||||
// else if (col_key === 'action') {
|
||||
// // 绑定系统选择框事件
|
||||
// cell_obj.find('[data-action]').click(function () {
|
||||
// var action = $(this).attr('data-action');
|
||||
// if (action === 'edit') {
|
||||
// $app.dlg_edit_host.show_edit(row_id);
|
||||
// } else if (action === 'account') {
|
||||
// $app.dlg_accounts.show(row_id);
|
||||
// }
|
||||
// });
|
||||
// } else if (col_key === 'ip') {
|
||||
// cell_obj.find('[data-toggle="popover"]').popover({trigger: 'hover'});
|
||||
// // } else if (col_key === 'account') {
|
||||
// // cell_obj.find('[data-action="add-account"]').click(function () {
|
||||
// // $app.dlg_accounts.show(row_id);
|
||||
// // });
|
||||
// } else if (col_key === 'account_count') {
|
||||
// cell_obj.find('[data-action="edit-account"]').click(function () {
|
||||
// $app.dlg_accounts.show(row_id);
|
||||
// });
|
||||
// }
|
||||
};
|
||||
|
||||
$app.check_host_all_selected = function (cb_stack) {
|
||||
|
@ -389,18 +388,48 @@ $app.on_table_session_header_created = function (header) {
|
|||
//header._table_ctrl.get_filter_ctrl('host_state').on_created();
|
||||
};
|
||||
|
||||
$app.get_selected_session = function (tbl) {
|
||||
$app.get_selected_sessions = function (tbl) {
|
||||
var records = [];
|
||||
var _objs = $('#' + $app.table_session.dom_id + ' tbody tr td input[data-check-box]');
|
||||
$.each(_objs, function (i, _obj) {
|
||||
if ($(_obj).is(':checked')) {
|
||||
var _row_data = tbl.get_row(_obj);
|
||||
records.push(_row_data.id);
|
||||
records.push(_row_data.sid);
|
||||
}
|
||||
});
|
||||
return records;
|
||||
};
|
||||
|
||||
$app.on_btn_kill_sessions_click = function () {
|
||||
$tp.notify_error('抱歉,此功能尚未实现!');
|
||||
var sessions = $app.get_selected_sessions($app.table_session);
|
||||
console.log(sessions);
|
||||
if (sessions.length === 0) {
|
||||
$tp.notify_error('请选择要强行终止的会话!');
|
||||
return;
|
||||
}
|
||||
|
||||
var _fn_sure = function (cb_stack, cb_args) {
|
||||
$tp.ajax_post_json('/ops/kill', {sessions: sessions},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
$app.table_session.load_data();
|
||||
$tp.notify_success('强行终止会话操作成功!');
|
||||
} else {
|
||||
$tp.notify_error('强行终止会话失败:' + tp_error_msg(ret.code, ret.message));
|
||||
}
|
||||
|
||||
cb_stack.exec();
|
||||
},
|
||||
function () {
|
||||
$tp.notify_error('网络故障,强行终止会话操作失败!');
|
||||
cb_stack.exec();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
$tp.dlg_confirm(cb_stack, {
|
||||
msg: '您确定要强行终止这些会话吗?',
|
||||
fn_yes: _fn_sure
|
||||
});
|
||||
};
|
||||
|
|
|
@ -34,12 +34,12 @@
|
|||
|
||||
<!-- begin page-nav -->
|
||||
<div class="table-extend-area">
|
||||
## <div class="table-extend-cell checkbox-select-all"><input id="table-session-select-all" type="checkbox"/></div>
|
||||
## <div class="table-extend-cell group-actions">
|
||||
## <div class="btn-group" role="group">
|
||||
## <button id="btn-kill-sessions" type="button" class="btn btn-danger"><i class="fa fa-times-circle fa-fw"></i> 强行中断</button>
|
||||
## </div>
|
||||
## </div>
|
||||
<div class="table-extend-cell checkbox-select-all"><input id="table-session-select-all" type="checkbox"/></div>
|
||||
<div class="table-extend-cell group-actions">
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btn-kill-sessions" type="button" class="btn btn-danger"><i class="fa fa-times-circle fa-fw"></i> 强行中断</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-extend-cell table-item-counter">
|
||||
<ol id="table-session-paging"></ol>
|
||||
</div>
|
||||
|
@ -59,4 +59,10 @@
|
|||
</div>
|
||||
<!-- end of box -->
|
||||
|
||||
<div class="box">
|
||||
<p>说明:</p>
|
||||
<ul class="help-list">
|
||||
<li>注意:强制中断会话时,相同会话ID的会话(例如使用SecureCRT或者xShell客户端的“克隆会话”功能打开的会话)均会被中断。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -162,6 +162,8 @@ controllers = [
|
|||
(r'/ops/get-remotes', ops.DoGetRemotesHandler),
|
||||
# - [json] 构建授权映射表
|
||||
(r'/ops/build-auz-map', ops.DoBuildAuzMapHandler),
|
||||
# - [json] 强行终止指定会话
|
||||
(r'/ops/kill', ops.DoKillSessionsHandler),
|
||||
|
||||
# ====================================================
|
||||
# 审计相关
|
||||
|
|
|
@ -736,6 +736,32 @@ class DoGetRemotesHandler(TPBaseJsonHandler):
|
|||
self.write_json(err, data=ret)
|
||||
|
||||
|
||||
class DoKillSessionsHandler(TPBaseJsonHandler):
|
||||
@tornado.gen.coroutine
|
||||
def post(self):
|
||||
ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
|
||||
if ret != TPE_OK:
|
||||
return
|
||||
|
||||
args = self.get_argument('args', None)
|
||||
if args is None:
|
||||
return self.write_json(TPE_PARAM)
|
||||
try:
|
||||
args = json.loads(args)
|
||||
except:
|
||||
return self.write_json(TPE_JSON_FORMAT)
|
||||
|
||||
try:
|
||||
sessions = args['sessions']
|
||||
except:
|
||||
return self.write_json(TPE_PARAM)
|
||||
|
||||
req = {'method': 'kill_sessions', 'param': {'sessions': sessions}}
|
||||
_yr = core_service_async_post_http(req)
|
||||
_err, _ = yield _yr
|
||||
self.write_json(_err)
|
||||
|
||||
|
||||
class DoBuildAuzMapHandler(TPBaseJsonHandler):
|
||||
def post(self):
|
||||
ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
|
||||
|
|
|
@ -100,8 +100,8 @@ def get_records(handler, sql_filter, sql_order, sql_limit, sql_restrict, sql_exc
|
|||
s.order_by('r.id', _sort)
|
||||
elif 'time_begin' == sql_order['name']:
|
||||
s.order_by('r.time_begin', _sort)
|
||||
# elif 'os_type' == sql_order['name']:
|
||||
# s.order_by('h.os_type', _sort)
|
||||
elif 'sid' == sql_order['name']:
|
||||
s.order_by('r.sid', _sort)
|
||||
# elif 'cid' == sql_order['name']:
|
||||
# s.order_by('h.cid', _sort)
|
||||
# elif 'state' == sql_order['name']:
|
||||
|
|
Loading…
Reference in New Issue