A 安全设置增加登录IP绑定设置

pull/442/head
vapao 2021-12-23 21:50:06 +08:00
parent 3b5ec14185
commit eb0ab71017
5 changed files with 37 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import json
KEYS_DEFAULT = { KEYS_DEFAULT = {
'MFA': {'enable': False}, 'MFA': {'enable': False},
'verify_ip': True, 'verify_ip': True,
'bind_ip': True,
'ldap_service': {}, 'ldap_service': {},
'spug_key': None, 'spug_key': None,
'api_key': None, 'api_key': None,

View File

@ -10,15 +10,18 @@ from libs.mail import Mail
from libs.spug import send_login_wx_code from libs.spug import send_login_wx_code
from libs.mixins import AdminView from libs.mixins import AdminView
from apps.setting.utils import AppSetting from apps.setting.utils import AppSetting
from apps.setting.models import Setting from apps.setting.models import Setting, KEYS_DEFAULT
from copy import deepcopy
import platform import platform
import ldap import ldap
class SettingView(AdminView): class SettingView(AdminView):
def get(self, request): def get(self, request):
data = Setting.objects.all() response = deepcopy(KEYS_DEFAULT)
return json_response([x.to_view() for x in data]) for item in Setting.objects.all():
response[item.key] = item.real_val
return json_response(response)
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(

View File

@ -5,6 +5,7 @@ from django.utils.deprecation import MiddlewareMixin
from django.conf import settings from django.conf import settings
from .utils import json_response, get_request_real_ip from .utils import json_response, get_request_real_ip
from apps.account.models import User from apps.account.models import User
from apps.setting.utils import AppSetting
import traceback import traceback
import time import time
@ -33,11 +34,12 @@ class AuthenticationMiddleware(MiddlewareMixin):
if access_token and len(access_token) == 32: if access_token and len(access_token) == 32:
x_real_ip = get_request_real_ip(request.headers) x_real_ip = get_request_real_ip(request.headers)
user = User.objects.filter(access_token=access_token).first() user = User.objects.filter(access_token=access_token).first()
if user and x_real_ip == user.last_ip and user.token_expired >= time.time() and user.is_active: if user and user.token_expired >= time.time() and user.is_active:
request.user = user if x_real_ip == user.last_ip or AppSetting.get_default('bind_ip') is False:
user.token_expired = time.time() + 8 * 60 * 60 request.user = user
user.save() user.token_expired = time.time() + 8 * 60 * 60
return None user.save()
return None
response = json_response(error="验证失败,请重新登录") response = json_response(error="验证失败,请重新登录")
response.status_code = 401 response.status_code = 401
return response return response

View File

@ -12,6 +12,7 @@ import store from './store';
export default observer(function () { export default observer(function () {
const [verify_ip, setVerifyIP] = useState(store.settings.verify_ip); const [verify_ip, setVerifyIP] = useState(store.settings.verify_ip);
const [bind_ip, setBindIP] = useState(store.settings.bind_ip);
const [mfa, setMFA] = useState(store.settings.MFA || {}); const [mfa, setMFA] = useState(store.settings.MFA || {});
const [code, setCode] = useState(); const [code, setCode] = useState();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
@ -36,6 +37,15 @@ export default observer(function () {
}) })
} }
function handleChangeBindIP(v) {
setBindIP(v);
http.post('/api/setting/', {data: [{key: 'bind_ip', value: v}]})
.then(() => {
message.success('设置成功');
store.fetchSettings()
})
}
function handleChangeMFA(v) { function handleChangeMFA(v) {
if (v && !store.settings.spug_key) return message.error('开启MFA认证需要先在基本设置中配置调用凭据'); if (v && !store.settings.spug_key) return message.error('开启MFA认证需要先在基本设置中配置调用凭据');
v ? setVisible(true) : handleMFAModify(false) v ? setVisible(true) : handleMFAModify(false)
@ -66,13 +76,24 @@ export default observer(function () {
<Form layout="vertical" style={{maxWidth: 500}}> <Form layout="vertical" style={{maxWidth: 500}}>
<Form.Item <Form.Item
label="访问IP校验" label="访问IP校验"
extra="建议开启校验是否获取了真实的访问者IP防止因为增加的反向代理层导致基于IP的安全策略失效当校验失败时会在登录时弹窗提醒。如果你在内网部署且仅在内网使用可以关闭该特性。"> extra={<span>建议开启校验是否获取了真实的访问者IP防止因为增加的反向代理层导致基于IP的安全策略失效当校验失败时会在登录时弹窗提醒如果你在内网部署且仅在内网使用可以关闭该特性<a
href="https://spug.cc/docs/practice/#%E5%AE%89%E5%85%A8%E6%80%A7%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97"
target="_blank" rel="noopener noreferrer">为什么没有获取到真实IP</a></span>}>
<Switch <Switch
checkedChildren="开启" checkedChildren="开启"
unCheckedChildren="关闭" unCheckedChildren="关闭"
onChange={handleChangeVerifyIP} onChange={handleChangeVerifyIP}
checked={verify_ip}/> checked={verify_ip}/>
</Form.Item> </Form.Item>
<Form.Item
label="登录IP绑定"
extra="强烈建议开启当开启后会把登录凭证与IP进行绑定当该登录凭证通过其他IP访问时将自动失效。如非必要切勿关闭该特性">
<Switch
checkedChildren="开启"
unCheckedChildren="关闭"
onChange={handleChangeBindIP}
checked={bind_ip}/>
</Form.Item>
<Form.Item <Form.Item
label="登录MFA两步认证" label="登录MFA两步认证"
style={{marginTop: 24}} style={{marginTop: 24}}

View File

@ -14,11 +14,7 @@ class Store {
fetchSettings = () => { fetchSettings = () => {
this.isFetching = true; this.isFetching = true;
http.get('/api/setting/') http.get('/api/setting/')
.then(res => { .then(res => this.settings = res)
for (let item of res) {
this.settings[item.key] = item.value;
}
})
.finally(() => this.isFetching = false) .finally(() => this.isFetching = false)
}; };