From 9ce271d691f8f6641f90bb9065f75c75c00d86fd Mon Sep 17 00:00:00 2001 From: zy7y <13271962515@163.com> Date: Tue, 13 Sep 2022 13:31:15 +0800 Subject: [PATCH] feat: api visit auth --- backend/controller/role.py | 13 ++---- backend/controller/user.py | 10 +---- backend/core/exceptions.py | 21 ++++++++- backend/core/security.py | 39 +++++++++++++++-- backend/dbhelper/menu.py | 26 +++++++++++ backend/dbhelper/role.py | 2 +- backend/main.py | 6 +-- backend/mini.db-shm | Bin 32768 -> 32768 bytes backend/mini.db-wal | Bin 399672 -> 399672 bytes backend/models/menu.py | 1 - backend/router/url.py | 83 ++++++++++++++++++------------------ backend/schemas/menu.py | 1 - backend/tests/test_case.py | 55 ++++++++---------------- frontend/src/stores/user.js | 11 ++++- frontend/src/views/main.vue | 11 ++++- 15 files changed, 170 insertions(+), 109 deletions(-) diff --git a/backend/controller/role.py b/backend/controller/role.py index d9e1222..6579935 100644 --- a/backend/controller/role.py +++ b/backend/controller/role.py @@ -4,15 +4,10 @@ from fastapi import Query from core.utils import list_to_tree from dbhelper.relation import role_assigned_menu -from dbhelper.role import ( - del_role, - get_role, - get_role_menus, - get_roles, - new_role, - put_role, -) -from schemas import ListAll, Response, RoleIn, RoleInfo, RoleMenuIn, RoleQuery, RoleRead +from dbhelper.role import (del_role, get_role, get_role_menus, get_roles, + new_role, put_role) +from schemas import (ListAll, Response, RoleIn, RoleInfo, RoleMenuIn, + RoleQuery, RoleRead) async def role_add(data: RoleIn) -> Response[RoleInfo]: diff --git a/backend/controller/user.py b/backend/controller/user.py index 7a6003b..81e9647 100644 --- a/backend/controller/user.py +++ b/backend/controller/user.py @@ -1,14 +1,8 @@ from fastapi import Query from core.security import get_password_hash -from dbhelper.user import ( - del_user, - get_user, - get_user_info, - get_users, - insert_user, - put_user, -) +from dbhelper.user import (del_user, get_user, get_user_info, get_users, + insert_user, put_user) from schemas import Response, UserAdd, UserInfo, UserPut, UserQuery, UserRead from schemas.common import ListAll diff --git a/backend/core/exceptions.py b/backend/core/exceptions.py index dcd0c5e..cc05e55 100644 --- a/backend/core/exceptions.py +++ b/backend/core/exceptions.py @@ -1,6 +1,23 @@ from fastapi.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse class TokenAuthFailure(HTTPException): - status_code = 401 - detail = "认证失败" + + pass + + +class PermissionsError(HTTPException): + pass + + +async def http_exception(request: Request, exc: HTTPException): + return JSONResponse( + {"msg": exc.detail, "code": exc.status_code, "data": None}, + status_code=exc.status_code, + headers=exc.headers, + ) + + +exception_handlers = {HTTPException: http_exception} diff --git a/backend/core/security.py b/backend/core/security.py index c56d9f2..c178d0d 100644 --- a/backend/core/security.py +++ b/backend/core/security.py @@ -1,13 +1,15 @@ from datetime import datetime, timedelta from typing import Optional -from fastapi import Depends +from fastapi import Depends, Request from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from jose import JWTError, jwt from passlib.context import CryptContext -from core.exceptions import TokenAuthFailure -from dbhelper.user import get_user +from core.exceptions import PermissionsError, TokenAuthFailure +from dbhelper.menu import get_apis, get_has_api +from dbhelper.user import get_user, get_user_info +from models import UserModel # JWT SECRET_KEY = "lLNiBWPGiEmCLLR9kRGidgLY7Ac1rpSWwfGzTJpTmCU" @@ -59,4 +61,33 @@ async def check_token(security: HTTPAuthorizationCredentials = Depends(bearer)): username: str = payload.get("sub") return await get_user({"username": username}) except JWTError: - raise TokenAuthFailure + raise TokenAuthFailure(403, "认证失败") + + +async def check_permissions(request: Request, user: UserModel = Depends(check_token)): + """检查接口权限""" + # 查询当前激活角色 + result = await get_user_info(user) + active_rid = result["roles"][0]["id"] + + # 白名单 + whitelist = [f"/user/{user.id}", f"/role/{active_rid}/menu"] + flag = request.url.path in whitelist and request.method == "GET" + if flag: + return + + api = request.url.path + for k, v in request.path_params.items(): + api = api.replace(v, "{%s}" % k) + # 方法1. 每一次去查数据库 + # result = await get_has_api(active_rid, api, request.method) + + # 2. 登录之后查一次 后面去结果查 todo 更新权限时需要更新 , 最好结果放redis + cache_key = f"{user.username}_{active_rid}" + # 缓存到fastapi 应用实例中 + if not hasattr(request.app.state, cache_key): + setattr(request.app.state, cache_key, await get_apis(active_rid)) + if {"api": api, "method": request.method} not in getattr( + request.app.state, cache_key + ): + raise PermissionsError(403, detail="无权访问") diff --git a/backend/dbhelper/menu.py b/backend/dbhelper/menu.py index 1695c61..2c0c37b 100644 --- a/backend/dbhelper/menu.py +++ b/backend/dbhelper/menu.py @@ -1,3 +1,5 @@ +from tortoise import connections + from models import MenuModel from schemas.menu import MenuIn @@ -41,3 +43,27 @@ async def get_menu(kwargs): async def del_menu(mid: int): """删除用户""" return await MenuModel.filter(id=mid).update(status=9) + + +async def get_has_api(pk: int, api: str, method: str): + """获取角色接口权限 每次来查数据库""" + db = connections.get("default") + return await db.execute_query_dict( + """ + select m.api, m.method + FROM sys_menu as m, sys_role_menu as srm WHERE m.id = srm.mid + AND srm.rid = (?) and m.api = (?) and m.method = (?) and m.status != 9""", + [pk, api, method], + ) + + +async def get_apis(pk: int): + """返回当前角色拥有的接口权限列表""" + db = connections.get("default") + return await db.execute_query_dict( + """ + select m.api, m.method + FROM sys_menu as m, sys_role_menu as srm WHERE m.id = srm.mid + AND srm.rid = (?) and m.status != 9""", + [pk], + ) diff --git a/backend/dbhelper/role.py b/backend/dbhelper/role.py index 5fab1fe..9af9309 100644 --- a/backend/dbhelper/role.py +++ b/backend/dbhelper/role.py @@ -11,7 +11,7 @@ async def get_role_menus(rid: int): db = connections.get("default") return await db.execute_query_dict( """ - select m.id, m.name, m.meta, m.path, m.type, m.component, m.pid, m.identifier, m.regx,m.api, m.method + select m.id, m.name, m.meta, m.path, m.type, m.component, m.pid, m.identifier FROM sys_menu as m, sys_role_menu WHERE m.id = sys_role_menu.mid AND sys_role_menu.rid = (?) AND m.`status` = 1""", [rid], diff --git a/backend/main.py b/backend/main.py index 42fd74d..889a69d 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from core.events import close_orm, init_orm +from core.exceptions import exception_handlers from core.log import logger from core.middleware import middlewares from router.url import routes @@ -10,14 +11,13 @@ app = FastAPI( on_shutdown=[close_orm], routes=routes, middleware=middlewares, + exception_handlers=exception_handlers, ) if __name__ == "__main__": import uvicorn for i in app.routes: - logger.info( - f"{i.path}, {i.methods}, {i.path_regex}, {i.__dict__.get('summary')}, {i.endpoint}" - ) + logger.info(f"{i.path}, {i.methods}, {i.__dict__.get('summary')}, {i.endpoint}") uvicorn.run("main:app", reload=True) diff --git a/backend/mini.db-shm b/backend/mini.db-shm index cb9b4213c40b53af18703d07ba9683c01f40c29c..80e612c2490c85de8d5e708399bccb6a59894bf5 100644 GIT binary patch delta 112 zcmZo@U}|V!N|1P@%K!t63=9H^Kn^z$$G&=c_-b9_sn8{fV#cbM6_pr|zuPNw^b@J- OCnhK`CT?u3uLl5~nj*3Q delta 112 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 QdTKUZqz3xWZI9sp12D+HDF6Tf diff --git a/backend/models/menu.py b/backend/models/menu.py index 4f7e57b..e36676f 100644 --- a/backend/models/menu.py +++ b/backend/models/menu.py @@ -15,7 +15,6 @@ class MenuModel(Table): identifier = fields.CharField(max_length=30, description="权限标识 user:add", null=True) api = fields.CharField(max_length=128, description="接口地址", null=True) method = fields.CharField(max_length=10, description="接口请求方式", null=True) - regx = fields.CharField(max_length=50, description="接口地址正则表达式", null=True) class Meta: table = "sys_menu" diff --git a/backend/router/url.py b/backend/router/url.py index ef6784b..631b753 100644 --- a/backend/router/url.py +++ b/backend/router/url.py @@ -4,17 +4,11 @@ from fastapi import Depends, routing from controller.common import about, login from controller.menu import menu_add, menu_arr, menu_del -from controller.role import ( - assigned_menu, - role_add, - role_arr, - role_del, - role_has_menu, - role_put, - role_query, -) -from controller.user import user_add, user_arr, user_del, user_info, user_list, user_put -from core.security import check_token +from controller.role import (assigned_menu, role_add, role_arr, role_del, + role_has_menu, role_put, role_query) +from controller.user import (user_add, user_arr, user_del, user_info, + user_list, user_put) +from core.security import check_permissions class Route(routing.APIRoute): @@ -113,48 +107,55 @@ class Route(routing.APIRoute): ) +has_perm = {"dependencies": [Depends(check_permissions)]} + routes = [ Route.post("/login", endpoint=login, tags=["公共"], summary="登录"), - Route.get("/about", endpoint=about, tags=["公共"], summary="关于"), + Route.get("/about", endpoint=about, tags=["公共"], summary="关于", **has_perm), # 用户管理 - Route.get("/user", endpoint=user_arr, tags=["用户管理"], summary="用户列表"), - Route.post("/user", endpoint=user_add, tags=["用户管理"], summary="用户新增"), + Route.get("/user", endpoint=user_arr, tags=["用户管理"], summary="用户列表", **has_perm), + Route.post("/user", endpoint=user_add, tags=["用户管理"], summary="用户新增", **has_perm), Route.delete( - "/user/{pk}", - endpoint=user_del, - tags=["用户管理"], - summary="用户删除", + "/user/{pk}", endpoint=user_del, tags=["用户管理"], summary="用户删除", **has_perm ), - Route.put("/user/{pk}", endpoint=user_put, tags=["用户管理"], summary="用户更新"), - Route.get("/user/{pk}", endpoint=user_info, tags=["用户管理"], summary="用户信息"), - Route.post("/user/query", endpoint=user_list, tags=["用户管理"], summary="用户列表查询"), - # 角色管理, - Route.get("/role", endpoint=role_arr, tags=["角色管理"], summary="角色列表"), - Route.post("/role", endpoint=role_add, tags=["角色管理"], summary="角色新增"), - Route.delete( - "/role/{pk}", - endpoint=role_del, - tags=["角色管理"], - summary="角色删除", - dependencies=[Depends(check_token)], + Route.put( + "/user/{pk}", endpoint=user_put, tags=["用户管理"], summary="用户更新", **has_perm ), Route.get( - "/role/{rid}/menu", endpoint=role_has_menu, tags=["角色管理"], summary="查询角色拥有权限" + "/user/{pk}", endpoint=user_info, tags=["用户管理"], summary="用户信息", **has_perm ), - Route.put("/role", endpoint=role_put, tags=["角色管理"], summary="角色更新"), - Route.post("/role/query", endpoint=role_query, tags=["角色管理"], summary="角色条件查询"), Route.post( - "/role/assigned/menu", endpoint=assigned_menu, tags=["角色管理"], summary="角色分配菜单" + "/user/query", endpoint=user_list, tags=["用户管理"], summary="用户列表查询", **has_perm + ), + # 角色管理, + Route.get("/role", endpoint=role_arr, tags=["角色管理"], summary="角色列表", **has_perm), + Route.post("/role", endpoint=role_add, tags=["角色管理"], summary="角色新增", **has_perm), + Route.delete( + "/role/{pk}", endpoint=role_del, tags=["角色管理"], summary="角色删除", **has_perm + ), + Route.get( + "/role/{rid}/menu", + endpoint=role_has_menu, + tags=["角色管理"], + summary="查询角色拥有权限", + **has_perm + ), + Route.put("/role", endpoint=role_put, tags=["角色管理"], summary="角色更新", **has_perm), + Route.post( + "/role/query", endpoint=role_query, tags=["角色管理"], summary="角色条件查询", **has_perm + ), + Route.post( + "/role/assigned/menu", + endpoint=assigned_menu, + tags=["角色管理"], + summary="角色分配菜单", + **has_perm ), # 菜单新增 - Route.get("/menu", endpoint=menu_arr, tags=["菜单管理"], summary="菜单列表"), - Route.post("/menu", endpoint=menu_add, tags=["菜单管理"], summary="菜单新增"), + Route.get("/menu", endpoint=menu_arr, tags=["菜单管理"], summary="菜单列表", **has_perm), + Route.post("/menu", endpoint=menu_add, tags=["菜单管理"], summary="菜单新增", **has_perm), Route.delete( - "/menu/{pk}", - endpoint=menu_del, - tags=["菜单管理"], - summary="菜单删除", - dependencies=[Depends(check_token)], + "/menu/{pk}", endpoint=menu_del, tags=["菜单管理"], summary="菜单删除", **has_perm ), ] diff --git a/backend/schemas/menu.py b/backend/schemas/menu.py index 707670e..f8dcb58 100644 --- a/backend/schemas/menu.py +++ b/backend/schemas/menu.py @@ -15,7 +15,6 @@ class MenuBasic(BaseModel): identifier: Optional[str] = Field(default=None, description="权限标识符 -> 按钮显示") api: Optional[str] = Field(default=None, description="后端接口地址") method: Optional[str] = Field(default=None, description="接口请求方法") - regx: Optional[str] = Field(default=None, description="正则匹配") class MenuIn(MenuBasic): diff --git a/backend/tests/test_case.py b/backend/tests/test_case.py index 2ea916d..1e66d2f 100644 --- a/backend/tests/test_case.py +++ b/backend/tests/test_case.py @@ -51,7 +51,6 @@ params = [ identifier=None, api=None, method=None, - regx=None, ).dict(), ), ( @@ -66,7 +65,6 @@ params = [ identifier=None, api=None, method=None, - regx=None, ).dict(), ), # 组件 @@ -81,8 +79,7 @@ params = [ pid=1, identifier=None, api="/user", - method="{'GET'}", - regx="^/user$", + method="GET", ).dict(), ), ( @@ -96,8 +93,7 @@ params = [ pid=1, identifier=None, api="/role", - method="{'GET'}", - regx="^/role$", + method="GET", ).dict(), ), ( @@ -111,8 +107,7 @@ params = [ pid=1, identifier=None, api="/menu", - method="{'GET'}", - regx="^/menu$", + method="GET", ).dict(), ), ( @@ -126,8 +121,7 @@ params = [ pid=2, identifier=None, api="/about", - method="{'GET'}", - regx="^/about", + method="GET", ).dict(), ), # 按钮 @@ -142,8 +136,7 @@ params = [ pid=3, identifier="user:create", api="/user", - method="{'POST'}", - regx="^/user$", + method="POST", ).dict(), ), ( @@ -157,8 +150,7 @@ params = [ pid=3, identifier="user:delete", api="/user/{pk}", - method="{'DELETE'}", - regx="^/user/(?P[^/]+)$", + method="DELETE", ).dict(), ), ( @@ -172,8 +164,7 @@ params = [ pid=3, identifier="user:update", api="/user/{pk}", - method="{'PUT'}", - regx="^/user/(?P[^/]+)$", + method="PUT", ).dict(), ), ( @@ -187,8 +178,7 @@ params = [ pid=3, identifier="user:get", api="/user/{pk}", - method="{'GET'}", - regx="^/user/(?P[^/]+)$", + method="GET", ).dict(), ), ( @@ -202,8 +192,7 @@ params = [ pid=3, identifier="user:query", api="/user/query", - method="{'POST'}", - regx="^/user/query$", + method="POST", ).dict(), ), # 角色管理 @@ -218,8 +207,7 @@ params = [ pid=4, identifier="role:create", api="/role", - method="{'POST'}", - regx="^/role$", + method="POST", ).dict(), ), ( @@ -233,8 +221,7 @@ params = [ pid=4, identifier="role:delete", api="/role/{pk}", - method="{'DELETE'}", - regx="^/role/(?P[^/]+)$", + method="DELETE", ).dict(), ), ( @@ -248,8 +235,7 @@ params = [ pid=4, identifier=None, api="/role/{rid}/menu", - method="{'GET'}", - regx="^/role/(?P[^/]+)/menu$", + method="GET", ).dict(), ), ( @@ -263,8 +249,7 @@ params = [ pid=4, identifier="", api="/role/query", - method="{'POST'}", - regx="^/role/query$", + method="POST", ).dict(), ), ( @@ -278,8 +263,7 @@ params = [ pid=4, identifier="role:assign", api="/role/assigned/menu", - method="{'POST'}", - regx="^/role/assigned/menu$", + method="POST", ).dict(), ), ( @@ -293,8 +277,7 @@ params = [ pid=4, identifier="role:update", api="/role", - method="{'PUT'}", - regx="^/role$", + method="PUT", ).dict(), ), # 菜单管理的权限 @@ -309,8 +292,7 @@ params = [ pid=5, identifier="menu:create", api="/menu", - method="{'POST'}", - regx="^/menu$", + method="POST", ).dict(), ), ( @@ -324,8 +306,7 @@ params = [ pid=5, identifier="menu:delete", api="/menu/{pk}", - method="{'DELETE'}", - regx="/menu/(?P[^/]+)$", + method="DELETE", ).dict(), ), # 分配权限 @@ -333,7 +314,7 @@ params = [ "/role/assigned/menu", RoleMenuIn(rid=1, menus=[num for num in range(1, 20)]).dict(), ), - ("/role/assigned/menu", RoleMenuIn(rid=2, menus=[3, 7, 8, 9, 10, 11]).dict()), + ("/role/assigned/menu", RoleMenuIn(rid=2, menus=[1, 3, 7, 8, 9, 11]).dict()), ] diff --git a/frontend/src/stores/user.js b/frontend/src/stores/user.js index 635b81d..1b14eb2 100644 --- a/frontend/src/stores/user.js +++ b/frontend/src/stores/user.js @@ -12,6 +12,14 @@ export const userStore = defineStore('user', () => { // getter const accessToken = computed(() => 'Bearer ' + token.value) + // setup store 不提供$reset 需要自己重置 + // https://github.com/vuejs/pinia/issues/1056 + const $reset = () => { + token.value = "" + userInfo.value = {} + userMenus.value = [] + } + // 非setup语法时的actions const loginAction = async (data) => { @@ -34,7 +42,8 @@ export const userStore = defineStore('user', () => { ElMessage.success("登录成功.") } - return { token, accessToken, userInfo, userMenus, loginAction } + return { token, accessToken, userInfo, userMenus, + $reset, loginAction } }, { persist: true, // 解决pinia刷新时数据丢失问题 }) diff --git a/frontend/src/views/main.vue b/frontend/src/views/main.vue index 55ca234..fc4161d 100644 --- a/frontend/src/views/main.vue +++ b/frontend/src/views/main.vue @@ -1,5 +1,12 @@