forked from TencentBlueKing/bk-user
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
60 changed files
with
6,179 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,10 @@ jobs: | |
uses: actions/setup-python@v2 | ||
with: | ||
python-version: "3.10" | ||
- name: create idp plugin symbolic link | ||
run: | | ||
ln -s $(pwd)/src/idp-plugins/idp_plugin $(pwd)/src/bk-login/bklogin | ||
ln -s $(pwd)/src/idp-plugins/idp_plugin $(pwd)/src/bk-user/bkuser | ||
- name: Format with black | ||
run: | | ||
pip install black==23.7.0 click==8.1.6 | ||
|
@@ -52,6 +56,10 @@ jobs: | |
uses: actions/setup-python@v4 | ||
with: | ||
python-version: "3.10" | ||
- name: create idp plugin symbolic link | ||
run: | | ||
ln -s $(pwd)/src/idp-plugins/idp_plugin $(pwd)/src/bk-login/bklogin | ||
ln -s $(pwd)/src/idp-plugins/idp_plugin $(pwd)/src/bk-user/bkuser | ||
- name: Set up Poetry | ||
uses: abatilo/[email protected] | ||
with: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
FROM node:18.17.1-bullseye-slim AS StaticBuilding | ||
ENV NPM_VERSION 9.6.7 | ||
|
||
COPY src/bk-login/pages / | ||
WORKDIR / | ||
RUN npm install | ||
RUN npm run build | ||
|
||
FROM python:3.10.12-slim-bullseye | ||
USER root | ||
|
||
RUN rm /etc/apt/sources.list && \ | ||
echo "deb https://mirrors.tencent.com/debian bullseye main" >> /etc/apt/sources.list && \ | ||
echo "deb https://mirrors.tencent.com/debian-security bullseye-security main" >> /etc/apt/sources.list && \ | ||
echo "deb https://mirrors.tencent.com/debian bullseye-updates main" >> /etc/apt/sources.list | ||
|
||
RUN mkdir ~/.pip && printf '[global]\nindex-url = https://mirrors.tencent.com/pypi/simple/' > ~/.pip/pip.conf | ||
|
||
RUN apt-get update && apt-get install -y default-libmysqlclient-dev build-essential pkg-config | ||
|
||
ENV LC_ALL=C.UTF-8 \ | ||
LANG=C.UTF-8 | ||
|
||
RUN pip install --upgrade pip setuptools | ||
RUN pip install poetry==1.5.1 | ||
|
||
WORKDIR /app | ||
COPY src/bk-login/pyproject.toml /app | ||
COPY src/bk-login/poetry.lock /app | ||
RUN poetry config virtualenvs.create false && poetry install --only main | ||
|
||
COPY src/bk-login/bklogin /app/bklogin | ||
COPY src/bk-login/bin /app/bin | ||
COPY src/bk-login/manage.py /app | ||
|
||
COPY --from=StaticBuilding /dist /app/staticfiles | ||
COPY --from=StaticBuilding /dist/index.html /app/templates/index.html | ||
|
||
CMD ["bash", "/app/bin/start.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/bin/bash | ||
|
||
LISTEN_PORT="${PORT:=8000}" | ||
gunicorn bklogin.wsgi -w 8 --threads 2 --max-requests 1024 --max-requests-jitter 50 --worker-class gevent -b [::]:$LISTEN_PORT --access-logfile - --error-logfile - --access-logformat '[%(h)s] %({request_id}i)s %(u)s %(t)s "%(r)s" %(s)s %(D)s %(b)s "%(f)s" "%(a)s"' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
## -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
from django.apps import AppConfig | ||
|
||
|
||
class AuthenticationConfig(AppConfig): | ||
default_auto_field = "django.db.models.BigAutoField" | ||
name = "bklogin.authentication" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
REDIRECT_FIELD_NAME = "c_url" | ||
|
||
SIGN_IN_TENANT_ID_SESSION_KEY = "sign_in_tenant_id" | ||
|
||
SUPPORT_SIGN_IN_TENANT_USER_IDS_SESSION_KEY = "support_sign_in_tenant_user_ids" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
import datetime | ||
import logging | ||
import random | ||
import string | ||
import time | ||
from typing import Tuple | ||
from urllib.parse import unquote | ||
|
||
from blue_krill.encrypt.handler import EncryptHandler | ||
from django.conf import settings | ||
from django.utils import timezone | ||
from django.utils.encoding import force_bytes | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from .models import BkToken | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class BkTokenProcessor: | ||
def __init__(self, encrypt_secret_key: bytes): | ||
# Token加密密钥 | ||
self.encrypt_secret_key = encrypt_secret_key | ||
|
||
@staticmethod | ||
def _salt(length: int = 8) -> str: | ||
"""生成长度为length 的随机字符串""" | ||
allow_chars = string.ascii_letters + string.digits | ||
return "".join([random.choice(allow_chars) for __ in range(length)]) | ||
|
||
def generate(self, username: str, expires: int) -> str: | ||
"""token生成""" | ||
# 加盐 | ||
plain_token = "%s|%s|%s" % (expires, username, self._salt()) | ||
|
||
# 加密 | ||
return EncryptHandler(secret_key=self.encrypt_secret_key).encrypt(plain_token) | ||
|
||
def parse(self, bk_token: str) -> Tuple[str, int]: | ||
"""token解析""" | ||
try: | ||
plain_bk_token = EncryptHandler(secret_key=self.encrypt_secret_key).decrypt(bk_token) | ||
except Exception: | ||
logger.exception("参数[%s] 解析失败", bk_token) | ||
plain_bk_token = "" | ||
|
||
error_msg = _("参数 bk_token 非法") | ||
if not plain_bk_token: | ||
raise ValueError(error_msg) | ||
|
||
try: | ||
token_info = plain_bk_token.split("|") | ||
except Exception: | ||
logger.exception("分割 bk_token[%s] 失败", bk_token) | ||
raise ValueError(error_msg) | ||
|
||
if not token_info or len(token_info) < 3: # noqa: PLR2004 | ||
raise ValueError(error_msg) | ||
|
||
return token_info[1], int(token_info[0]) | ||
|
||
|
||
class BkTokenManager: | ||
def __init__(self): | ||
# Token加密密钥 | ||
self.bk_token_processor = BkTokenProcessor(encrypt_secret_key=force_bytes(settings.ENCRYPT_SECRET_KEY)) | ||
# Token 过期间隔 | ||
self.cookie_age = settings.BK_TOKEN_COOKIE_AGE | ||
# Token 无操作失效间隔 | ||
self.inactive_age = settings.BK_TOKEN_INACTIVE_AGE | ||
# Token 校验时间允许误差 | ||
self.offset_error_age = settings.BK_TOKEN_OFFSET_ERROR_AGE | ||
|
||
# Token生成失败的重试次数 | ||
self.allowed_retry_count = 5 | ||
|
||
def get_bk_token(self, username: str) -> Tuple[str, datetime.datetime]: | ||
""" | ||
生成用户的登录态 | ||
""" | ||
bk_token = "" | ||
expire_time = int(time.time()) | ||
# 重试5次 | ||
retry_count = 0 | ||
while not bk_token and retry_count < self.allowed_retry_count: | ||
now_time = int(time.time()) | ||
# Token过期时间 | ||
expire_time = now_time + self.cookie_age | ||
# Token 无操作失效时间 | ||
inactive_expire_time = now_time + self.inactive_age | ||
# 生成bk_token | ||
bk_token = self.bk_token_processor.generate(username, expire_time) | ||
# DB记录 | ||
try: | ||
BkToken.objects.create(token=bk_token, inactive_expire_time=inactive_expire_time) | ||
except Exception: # noqa: PERF203 | ||
logger.exception("Login ticket failed to be saved during ticket generation") | ||
# 循环结束前将bk_token置空后重新生成 | ||
bk_token = "" if retry_count + 1 < self.allowed_retry_count else bk_token | ||
retry_count += 1 | ||
|
||
return bk_token, datetime.datetime.fromtimestamp(expire_time, timezone.get_current_timezone()) | ||
|
||
def is_bk_token_valid(self, bk_token: str) -> Tuple[bool, str, str]: | ||
""" | ||
验证用户登录态 | ||
""" | ||
if not bk_token: | ||
return False, "", _("参数 bk_token 缺失") | ||
|
||
bk_token = unquote(bk_token) | ||
# 解析bk_token获取username和过期时间 | ||
try: | ||
username, expire_time = self.bk_token_processor.parse(bk_token) | ||
except ValueError as error: | ||
return False, "", str(error) | ||
|
||
# 检查DB是存在 | ||
try: | ||
bk_token_obj = BkToken.objects.get(token=bk_token) | ||
is_logout = bk_token_obj.is_logout | ||
inactive_expire_time = bk_token_obj.inactive_expire_time | ||
except Exception: | ||
return False, "", _("不存在 bk_token[%s] 的记录").format(bk_token) | ||
|
||
# token已注销 | ||
if is_logout: | ||
return False, "", _("登录态已注销") | ||
|
||
now_time = int(time.time()) | ||
# token有效期已过 | ||
if now_time > expire_time + self.offset_error_age: | ||
return False, "", _("登录态已过期") | ||
|
||
# token有效期大于当前时间的有效期 | ||
if expire_time - now_time > self.cookie_age + self.offset_error_age: | ||
return False, "", _("登录态有效期不合法") | ||
|
||
# token 无操作有效期已过 | ||
if now_time > inactive_expire_time + self.inactive_age: | ||
return False, "", _("长时间无操作,登录态已过期") | ||
|
||
# 更新 无操作有效期 | ||
try: | ||
BkToken.objects.filter(token=bk_token).update(inactive_expire_time=now_time + self.inactive_age) | ||
except Exception: | ||
logger.exception("update inactive_expire_time fail") | ||
|
||
return True, username, "" |
23 changes: 23 additions & 0 deletions
23
src/bk-login/bklogin/authentication/migrations/0001_initial.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Generated by Django 3.2.21 on 2023-09-27 02:34 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='BkToken', | ||
fields=[ | ||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('token', models.CharField(db_index=True, max_length=255, unique=True, verbose_name='登录票据')), | ||
('is_logout', models.BooleanField(default=False, verbose_name='票据是否已经执行过退出登录操作')), | ||
('inactive_expire_time', models.IntegerField(default=0, verbose_name='无操作失效时间戳')), | ||
], | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
from django.db import models | ||
|
||
|
||
class BkToken(models.Model): | ||
""" | ||
登录票据 | ||
""" | ||
|
||
token = models.CharField("登录票据", max_length=255, unique=True, db_index=True) | ||
# 是否已经退出登录 | ||
is_logout = models.BooleanField("票据是否已经执行过退出登录操作", default=False) | ||
# 无操作过期时间戳 | ||
inactive_expire_time = models.IntegerField("无操作失效时间戳", default=0) |
Oops, something went wrong.