Skip to content

Commit 6835a66

Browse files
authored
Merge pull request #43 from jiayuan929/apigw-api
feat: bklogin API 切换到 APIGW
2 parents 38d4223 + 06137ce commit 6835a66

File tree

8 files changed

+155
-74
lines changed

8 files changed

+155
-74
lines changed

backend/account/accounts.py

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
from django.shortcuts import render
2929

3030
from account.exceptions import AccessPermissionDenied
31+
from apigw.client import BkLoginClient
32+
from apigw.exceptions import BkLoginNoAccessPermission
3133
from bk_i18n.constants import BK_LANG_TO_DJANGO_LANG
3234
from common.log import logger
33-
from components.login import get_user, is_login
3435

3536

3637
class AccountSingleton(object):
@@ -59,47 +60,36 @@ class Account(AccountSingleton):
5960
# 线上 LOGIN_DOMAIN 为空
6061
BK_LOGIN_URL = "/login/"
6162

62-
# 蓝鲸统一登录约定的错误码, 表示用户认证成功,但用户无应用访问权限
63-
ACCESS_PERMISSION_DENIED_CODE = 1302403
64-
6563
def is_bk_token_valid(self, request):
6664
"""验证用户登录态."""
6765
bk_token = request.COOKIES.get(settings.BK_COOKIE_NAME, None)
6866
if not bk_token:
6967
return False, None
70-
ret, data = self.verify_bk_login(bk_token)
71-
# bk_token 无效
72-
if not ret:
68+
69+
# 校验并获取用户信息
70+
try:
71+
data = BkLoginClient().get_user(bk_token)
72+
except BkLoginNoAccessPermission as e:
73+
raise AccessPermissionDenied(e)
74+
except Exception:
7375
return False, None
76+
7477
# 检查用户是否存在用户表中
7578
username = data.get("bk_username", "")
7679
user_model = get_user_model()
7780
try:
7881
user = user_model._default_manager.get_by_natural_key(username)
79-
is_created_user = False
8082
except user_model.DoesNotExist:
8183
user = user_model.objects.create_user(username)
82-
is_created_user = True
8384
finally:
8485
try:
85-
ret, data = self.get_bk_user_info(bk_token)
86-
# 若获取用户信息失败,则用户可登录,但用户其他信息为空
87-
user.chname = data.get("chname", "")
88-
86+
user.chname = data.get("display_name", username)
8987
# 用户隐私信息置空,需要的时候直接从用户管理 API 中获取
9088
user.company = data.get("company", "")
9189
user.qq = ""
9290
user.phone = ""
9391
user.email = ""
9492
user.role = ""
95-
96-
# 仅新用户从用户管理同步权限
97-
# 用户创建后直接在桌面管理用户是否能进入到 admin 页面的权限
98-
if is_created_user:
99-
role = data.get("bk_role", "")
100-
is_superuser = True if role == 1 else False
101-
user.is_superuser = is_superuser
102-
user.is_staff = is_superuser
10393
user.save()
10494

10595
# 设置timezone session
@@ -110,34 +100,6 @@ def is_bk_token_valid(self, request):
110100
logger.error("Get and record user information failed:%s" % e)
111101
return True, user
112102

113-
def verify_bk_login(self, bk_token):
114-
"""请求平台接口验证登录是否失效"""
115-
code, message, data = is_login(bk_token)
116-
if code == 0:
117-
return True, data
118-
119-
if code == self.ACCESS_PERMISSION_DENIED_CODE:
120-
logger.info("No access permission: %s" % message)
121-
raise AccessPermissionDenied(message)
122-
123-
logger.error("Verification of user login token is invalid, code: %s, message: %s" % (code, message))
124-
return False, {}
125-
126-
def get_bk_user_info(self, bk_token):
127-
"""请求平台接口获取用户信息"""
128-
code, message, data = get_user(bk_token)
129-
if code == 0:
130-
return True, data
131-
132-
if code == self.ACCESS_PERMISSION_DENIED_CODE:
133-
logger.info("No access permission: %s" % message)
134-
raise AccessPermissionDenied(message)
135-
136-
logger.error(
137-
"Get user information from the request platform interface failed, code: %s, message: %s" % (code, message)
138-
)
139-
return False, {}
140-
141103
def build_callback_url(self, request, jump_url):
142104
callback = request.build_absolute_uri()
143105
login_scheme, login_netloc = urlparse(jump_url)[:2]

backend/components/login.py renamed to backend/apigw/__init__.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,3 @@
1717
1818
to the current version of the project delivered to anyone in the future.
1919
"""
20-
from components.esb import _call_esb_api
21-
from components.http import http_get
22-
23-
24-
def is_login(bk_token):
25-
"""
26-
校验登录态
27-
"""
28-
path = '/api/c/compapi/v2/bk_login/is_login/'
29-
_, code, message, data = _call_esb_api(http_get, path, {"bk_token": bk_token})
30-
return code, message, data
31-
32-
33-
def get_user(bk_token):
34-
"""
35-
校验登录态
36-
"""
37-
path = '/api/c/compapi/v2/bk_login/get_user/'
38-
_, code, message, data = _call_esb_api(http_get, path, {"bk_token": bk_token})
39-
return code, message, data

backend/apigw/bk_api.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
TencentBlueKing is pleased to support the open source community by making
4+
蓝鲸智云 - 蓝鲸桌面 (BlueKing - bkconsole) available.
5+
Copyright (C) 2022 THL A29 Limited,
6+
a Tencent company. All rights reserved.
7+
Licensed under the MIT License (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at http://opensource.org/licenses/MIT
10+
Unless required by applicable law or agreed to in writing,
11+
software distributed under the License is distributed on
12+
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
either express or implied. See the License for the
14+
specific language governing permissions and limitations under the License.
15+
16+
We undertake not to change the open source license (MIT license) applicable
17+
18+
to the current version of the project delivered to anyone in the future.
19+
"""
20+
from bkapi_client_core.apigateway import APIGatewayClient, Operation, OperationGroup, bind_property
21+
22+
23+
class Group(OperationGroup):
24+
# 校验 bk_token
25+
verify_bk_token = bind_property(
26+
Operation,
27+
name="verify_bk_token",
28+
method="GET",
29+
path="/login/api/v3/open/bk-tokens/verify/",
30+
)
31+
# 查询 bk_token 对应的用户信息
32+
get_bk_token_userinfo = bind_property(
33+
Operation,
34+
name="get_bk_token_userinfo",
35+
method="GET",
36+
path="/login/api/v3/open/bk-tokens/userinfo/",
37+
)
38+
39+
40+
class Client(APIGatewayClient):
41+
"""Bkapi bk-login client"""
42+
43+
_api_name = "bk-login"
44+
45+
api = bind_property(Group, name="api")

backend/apigw/client.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
TencentBlueKing is pleased to support the open source community by making
4+
蓝鲸智云 - 蓝鲸桌面 (BlueKing - bkconsole) available.
5+
Copyright (C) 2022 THL A29 Limited,
6+
a Tencent company. All rights reserved.
7+
Licensed under the MIT License (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at http://opensource.org/licenses/MIT
10+
Unless required by applicable law or agreed to in writing,
11+
software distributed under the License is distributed on
12+
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
either express or implied. See the License for the
14+
specific language governing permissions and limitations under the License.
15+
16+
We undertake not to change the open source license (MIT license) applicable
17+
18+
to the current version of the project delivered to anyone in the future.
19+
"""
20+
import logging
21+
22+
from bkapi_client_core.exceptions import APIGatewayResponseError, ResponseError
23+
from django.conf import settings
24+
25+
from apigw.bk_api import Client
26+
from apigw.exceptions import BkLoginGatewayServiceError, BkLoginNoAccessPermission
27+
28+
logger = logging.getLogger(__name__)
29+
30+
31+
class BkLoginClient:
32+
def __init__(self):
33+
client = Client(endpoint=settings.BK_API_URL_TMPL, stage="prod")
34+
client.update_bkapi_authorization(
35+
bk_app_code="bk_paas",
36+
bk_app_secret=settings.BK_APP_SECRET,
37+
)
38+
client.update_headers(self._prepare_headers())
39+
self.client = client.api
40+
41+
def _prepare_headers(self) -> dict:
42+
return {
43+
# 调用全租户网关时,网关会强制要求传递 X-Bk-Tenant-Id, 但不会实际校验值的有效性, 统一传 default
44+
"X-Bk-Tenant-Id": "default",
45+
}
46+
47+
def get_user(self, bk_token: str) -> dict:
48+
try:
49+
resp = self.client.get_bk_token_userinfo(params={"bk_token": bk_token})
50+
except (APIGatewayResponseError, ResponseError) as e:
51+
logger.exception(f"call bk login api error, detail: {e}")
52+
# 用户无权限时需要单独处理
53+
if e.response.status_code == 403:
54+
raise BkLoginNoAccessPermission(e.response.json()["error"]["message"])
55+
raise BkLoginGatewayServiceError("call bk login api error")
56+
57+
return resp["data"]

backend/apigw/exceptions.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
# TencentBlueKing is pleased to support the open source community by making
3+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
4+
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
5+
# Licensed under the MIT License (the "License"); you may not use this file except
6+
# in compliance with the License. You may obtain a copy of the License at
7+
#
8+
# http://opensource.org/licenses/MIT
9+
#
10+
# Unless required by applicable law or agreed to in writing, software distributed under
11+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12+
# either express or implied. See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# We undertake not to change the open source license (MIT license) applicable
16+
# to the current version of the project delivered to anyone in the future.
17+
18+
19+
class BkLoginGatewayServiceError(Exception):
20+
"""This error indicates that there's something wrong when operating bk-login's
21+
API Gateway resource. It's a wrapper class of API SDK's original exceptions
22+
"""
23+
24+
def __init__(self, message: str):
25+
super().__init__(message)
26+
self.message = message
27+
28+
29+
class BkLoginApiError(BkLoginGatewayServiceError):
30+
"""When calling the bk-login api, bk-login returns an error message,
31+
which needs to be captured and displayed to the user on the page
32+
"""
33+
34+
35+
class BkLoginNoAccessPermission(BkLoginGatewayServiceError):
36+
"""User login verification passed, but no access permission."""

backend/conf/settings_env.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
# 与 ESB 通信的密钥
5757
ESB_TOKEN = env.str("BK_PAAS_SECRET_KEY")
58+
BK_APP_SECRET = env.str("BK_PAAS_SECRET_KEY")
5859

5960
# website
6061
# domain
@@ -77,7 +78,7 @@
7778
BK_API_URL_TMPL = env.str("BK_API_URL_TMPL", "http://bkapi.example.com/api/{api_name}")
7879

7980
# 登录访问的域名,代码中会自动拼接 /login/ 地址
80-
# LOGIN_DOMAIN = env.str("BK_LOGIN_DOMAIN", "paas.example.com")
81+
LOGIN_DOMAIN = env.str("BK_LOGIN_DOMAIN", "")
8182
# PaaS3.0 开发者中心的访问地址,不填则展示 PaaS2.0 开发者中心访问地址
8283
BK_PAAS3_URL = env.str("BK_PAAS3_URL", "")
8384

backend/templates/desktop/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
</div>
126126
<div class="dock-startbtn">
127127
<a href="javascript:;" class="dock-tool-start">
128-
<img src="{{STATIC_URL}}img/getheadimg.jpg" onerror="javascript:this.src='{{STATIC_URL}}img/getheadimg.jpg';" class="indicator-header-img" title="{{request.user.username}}" style="width:40px;height:40px;border-radius: 25px;">
128+
<img src="{{STATIC_URL}}img/getheadimg.jpg" onerror="javascript:this.src='{{STATIC_URL}}img/getheadimg.jpg';" class="indicator-header-img" title="{{request.user.chname}}" style="width:40px;height:40px;border-radius: 25px;">
129129
</a>
130130
</div>
131131
</div>
@@ -159,7 +159,7 @@
159159
<div class="startmenu-selfinfo"></div>
160160
<ul class="startmenu">
161161
<li>
162-
<a><span class="startmenu-username">{{request.user.username}}</span></a>
162+
<a><span class="startmenu-username">{{request.user.chname}}</span></a>
163163
</li>
164164
<li><a href="{{BK_DOCS_URL_PREFIX}}" target="blank" class="">{% trans '文档中心' %}</a></li>
165165
<li><a href="javascript:;" class="about">{% trans '蓝鲸官网' %}</a></li>

backend/user_center/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
from django.utils import timezone, translation
2626
from django.utils.translation import gettext as _
2727

28-
from account.accounts import Account
2928
from account.decorators import is_superuser_perm
29+
from apigw.client import BkLoginClient
3030
from app.models import App
3131
from app_esb_auth.models import EsbAuthApplyReocrd
3232
from bk_i18n.constants import TIME_ZONE_LIST
@@ -62,7 +62,7 @@ def account(request):
6262

6363
# 获取用户基本信息
6464
bk_token = request.COOKIES.get(settings.BK_COOKIE_NAME, None)
65-
_, data = Account().get_bk_user_info(bk_token)
65+
data = BkLoginClient().get_user(bk_token)
6666
role = data.get("bk_role")
6767

6868
context = {

0 commit comments

Comments
 (0)