新增后台IP变动控制开关

优化后台插件管理显示
优化Fast.api.ajax方法返回
优化管理员日志显示
pull/150/head v1.0.0.20191101_beta
Karson 2019-10-31 23:36:54 +08:00
parent b6f2307737
commit 49facb7b7c
12 changed files with 87 additions and 78 deletions

View File

@ -7,7 +7,7 @@
//当前是否为关联查询 //当前是否为关联查询
$this->relationSearch = {%relationSearch%}; $this->relationSearch = {%relationSearch%};
//设置过滤方法 //设置过滤方法
$this->request->filter(['strip_tags']); $this->request->filter(['strip_tags', 'trim']);
if ($this->request->isAjax()) if ($this->request->isAjax())
{ {
//如果发送的来源是Selectpage则转发到Selectpage //如果发送的来源是Selectpage则转发到Selectpage

View File

@ -22,6 +22,8 @@ class Index extends Backend
public function _initialize() public function _initialize()
{ {
parent::_initialize(); parent::_initialize();
//移除HTML标签
$this->request->filter('trim,strip_tags,htmlspecialchars');
} }
/** /**

View File

@ -59,7 +59,7 @@ class Auth extends \fast\Auth
} }
$admin->loginfailure = 0; $admin->loginfailure = 0;
$admin->logintime = time(); $admin->logintime = time();
$admin->loginip = request()->ip(0, false); $admin->loginip = request()->ip();
$admin->token = Random::uuid(); $admin->token = Random::uuid();
$admin->save(); $admin->save();
Session::set("admin", $admin->toArray()); Session::set("admin", $admin->toArray());
@ -103,7 +103,7 @@ class Auth extends \fast\Auth
if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $admin->token)) { if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $admin->token)) {
return false; return false;
} }
$ip = request()->ip(0, false); $ip = request()->ip();
//IP有变动 //IP有变动
if ($admin->loginip != $ip) { if ($admin->loginip != $ip) {
return false; return false;
@ -183,11 +183,16 @@ class Auth extends \fast\Auth
if (Config::get('fastadmin.login_unique')) { if (Config::get('fastadmin.login_unique')) {
$my = Admin::get($admin['id']); $my = Admin::get($admin['id']);
if (!$my || $my['token'] != $admin['token']) { if (!$my || $my['token'] != $admin['token']) {
$this->logout();
return false; return false;
} }
} }
if (!isset($admin['loginip']) || $admin['loginip'] != request()->ip(0, false)) { //判断管理员IP是否变动
return false; if (Config::get('fastadmin.loginip_check')) {
if (!isset($admin['loginip']) || $admin['loginip'] != request()->ip()) {
$this->logout();
return false;
}
} }
$this->logined = true; $this->logined = true;
return true; return true;

View File

@ -35,7 +35,7 @@ class AdminLog extends Model
$username = $auth->isLogin() ? $auth->username : __('Unknown'); $username = $auth->isLogin() ? $auth->username : __('Unknown');
$content = self::$content; $content = self::$content;
if (!$content) { if (!$content) {
$content = request()->param(); $content = request()->param('', null, 'trim,strip_tags,htmlspecialchars');
foreach ($content as $k => $v) { foreach ($content as $k => $v) {
if (is_string($v) && strlen($v) > 200 || stripos($k, 'password') !== false) { if (is_string($v) && strlen($v) > 200 || stripos($k, 'password') !== false) {
unset($content[$k]); unset($content[$k]);

View File

@ -233,6 +233,7 @@
</tbody> </tbody>
</table> </table>
</script> </script>
<!--@formatter:off-->
<script id="operatetpl" type="text/html"> <script id="operatetpl" type="text/html">
<% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %> <% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
<% var label = labelarr[item.id % 5]; %> <% var label = labelarr[item.id % 5]; %>
@ -240,63 +241,62 @@
<div class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>"> <div class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
<% if(!addon){ %> <% if(!addon){ %>
<% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%>
<span class="btn-group"> <span class="btn-group">
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<a class="btn btn-xs btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;">
<span class="fa fa-caret-down"></span>
</a>
<ul class="dropdown-menu">
<% for(var j=0;j< item.releaselist.length;j++){ %>
<li><a href="javascript:;" class="btn-install" data-type="<%=item.price<=0?'free':'price';%>"
data-donateimage="<%=item.donateimage%>"
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
<% } %>
</ul>
</span>
<% }else{%>
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install" <a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<a class="btn btn-xs btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;"> <% } %>
<span class="fa fa-caret-down"></span>
<% if(item.demourl){ %>
<a href="<%=item.demourl%>" class="btn btn-xs btn-primary btn-info btn-demo" target="_blank">
<i class="fa fa-flash"></i> {:__('Demo')}
</a> </a>
<ul class="dropdown-menu"> <% } %>
<% for(var j=0;j< item.releaselist.length;j++){ %>
<li><a href="javascript:;" class="btn-install" data-type="<%=item.price<=0?'free':'price';%>"
data-donateimage="<%=item.donateimage%>"
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
<% } %>
</ul>
</span>
<% }else{%>
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<% } %>
<% if(item.demourl){ %>
<a href="<%=item.demourl%>" class="btn btn-xs btn-primary btn-info btn-demo" target="_blank">
<i class="fa fa-flash"></i> {:__('Demo')}
</a>
<% } %>
<% } else {%> <% } else {%>
<% if(addon.version!=item.version){%> <% if(addon.version!=item.version){%>
<% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%>
<span class="btn-group"> <span class="btn-group">
<a href="javascript:;" class="btn btn-xs btn-info btn-success btn-upgrade" <a href="javascript:;" class="btn btn-xs btn-info btn-success btn-upgrade"
data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a> data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a>
<a class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown" <a class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown"
href="javascript:;"> href="javascript:;">
<span class="fa fa-caret-down"></span> <span class="fa fa-caret-down"></span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<% for(var j=0;j< item.releaselist.length;j++){ %> <% for(var j=0;j< item.releaselist.length;j++){ %>
<li><a href="javascript:;" class="btn-upgrade" <li><a href="javascript:;" class="btn-upgrade"
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li> data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
<% } %> <% } %>
</ul> </ul>
</span> </span>
<% }else{%> <% }else{%>
<a href="javascript:;" class="btn btn-xs btn-info btn-upgrade" title="{:__('Upgrade')}" data-version="<%=item.version%>"><i <a href="javascript:;" class="btn btn-xs btn-info btn-upgrade" title="{:__('Upgrade')}" data-version="<%=item.version%>"><i
class="fa fa-cloud"></i> {:__('Upgrade')}</a> class="fa fa-cloud"></i> {:__('Upgrade')}</a>
<% }%> <% }%>
<% }%> <% }%>
<% if(addon.config){ %> <% if(addon.config){ %>
<a href="javascript:;" class="btn btn-xs btn-primary btn-config" title="{:__('Setting')}"><i class="fa fa-pencil"></i> <a href="javascript:;" class="btn btn-xs btn-primary btn-config" title="{:__('Setting')}"><i class="fa fa-pencil"></i>
{:__('Setting')}</a> {:__('Setting')}</a>
<% } %>
<a href="javascript:;" class="btn btn-xs btn-danger btn-uninstall" title="{:__('Uninstall')}"><i class="fa fa-times"></i>
{:__('Uninstall')}</a>
<% } %> <% } %>
<a href="javascript:;" class="btn btn-xs btn-danger btn-uninstall" title="{:__('Uninstall')}"><i class="fa fa-times"></i>
{:__('Uninstall')}</a>
<% } %>
</div> </div>
</script> </script>
<!--@formatter:on-->

View File

@ -9,7 +9,7 @@
{volist name="row" id="vo" } {volist name="row" id="vo" }
<tr> <tr>
<td>{:__($key)}</td> <td>{:__($key)}</td>
<td>{$vo}</td> <td>{$vo|htmlentities}</td>
</tr> </tr>
{/volist} {/volist}
</tbody> </tbody>

View File

@ -256,7 +256,7 @@ class Auth
try { try {
$salt = Random::alnum(); $salt = Random::alnum();
$newpassword = $this->getEncryptPassword($newpassword, $salt); $newpassword = $this->getEncryptPassword($newpassword, $salt);
$this->_user->save(['password' => $newpassword, 'salt' => $salt]); $this->_user->save(['loginfailure' => 0, 'password' => $newpassword, 'salt' => $salt]);
Token::delete($this->_token); Token::delete($this->_token);
//修改密码成功的事件 //修改密码成功的事件
@ -298,6 +298,8 @@ class Auth
//记录本次登录的IP和时间 //记录本次登录的IP和时间
$user->loginip = $ip; $user->loginip = $ip;
$user->logintime = $time; $user->logintime = $time;
//重置登录失败次数
$user->loginfailure = 0;
$user->save(); $user->save();

View File

@ -265,6 +265,8 @@ return [
'login_failure_retry' => true, 'login_failure_retry' => true,
//是否同一账号同一时间只能在一个地方登录 //是否同一账号同一时间只能在一个地方登录
'login_unique' => false, 'login_unique' => false,
//是否开启IP变动检测
'loginip_check' => true,
//登录页默认背景图 //登录页默认背景图
'login_background' => "/assets/img/loginbg.jpg", 'login_background' => "/assets/img/loginbg.jpg",
//是否启用多级菜单导航 //是否启用多级菜单导航
@ -272,7 +274,7 @@ return [
//自动检测更新 //自动检测更新
'checkupdate' => false, 'checkupdate' => false,
//版本号 //版本号
'version' => '1.0.0.20190930_beta', 'version' => '1.0.0.20191101_beta',
//API接口地址 //API接口地址
'api_url' => 'https://api.fastadmin.net', 'api_url' => 'https://api.fastadmin.net',
], ],

View File

@ -441,19 +441,17 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
var userinfo = Controller.api.userinfo.get(); var userinfo = Controller.api.userinfo.get();
var uid = userinfo ? userinfo.id : 0; var uid = userinfo ? userinfo.id : 0;
if ($(that).data("type") !== 'free') { if (parseInt(uid) === 0) {
if (parseInt(uid) === 0) { return Layer.alert(__('Not login tips'), {
return Layer.alert(__('Not login tips'), { title: __('Warning'),
title: __('Warning'), btn: [__('Login now')],
btn: [__('Login now'), __('Continue install')], yes: function (index, layero) {
yes: function (index, layero) { $(".btn-userinfo").trigger("click");
$(".btn-userinfo").trigger("click"); },
}, btn2: function () {
btn2: function () { install(name, version, false);
install(name, version, false); }
} });
});
}
} }
install(name, version, false); install(name, version, false);
}); });

View File

@ -83,7 +83,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
Fast.events.onAjaxError(ret, error); Fast.events.onAjaxError(ret, error);
} }
}, options); }, options);
$.ajax(options); return $.ajax(options);
}, },
//修复URL //修复URL
fixurl: function (url) { fixurl: function (url) {

View File

@ -743,7 +743,7 @@ define('fast',['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, u
Fast.events.onAjaxError(ret, error); Fast.events.onAjaxError(ret, error);
} }
}, options); }, options);
$.ajax(options); return $.ajax(options);
}, },
//修复URL //修复URL
fixurl: function (url) { fixurl: function (url) {

View File

@ -736,7 +736,7 @@ define('fast',['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, u
Fast.events.onAjaxError(ret, error); Fast.events.onAjaxError(ret, error);
} }
}, options); }, options);
$.ajax(options); return $.ajax(options);
}, },
//修复URL //修复URL
fixurl: function (url) { fixurl: function (url) {