PdServer是一个pythonAPI服务器,我相信当你在看到这篇内容时,你是真的需要一个可以实现各项功能的python API服务器,以实现为你的其它业务提供能力的需求。毕竟目前python拥有足够多的开源库,例如我们的爬虫,情感分析。
项目整体代码结构,我们已经在上一篇讲解,不太清楚可以先去了解一下。

在这篇文章中,我们将以实现一个login接口来进行演示,login非常重要,因为要获取token,这需要我们在每一个业务接口中带上,实现对用户的鉴权,否则不能执行。
在这个过程中,我们需要:
-
路由中接收一个"login"请求;
-
查询数据库进行鉴权;
-
JWT生成token;
-
将userinfo与token返回;
这个过程,我们基本上跑通了流程,当然其它的一些我们会在会续的文章中分享。
-
配置端口
SERVER_PORT作为监听端口,其源于config.ini配置项,由于需要在初次运行后,才会自动生成config.ini,因此,你可以在初始化配置中修改端口,如果你已经运行过,就会自动生成这个config.ini,可以在config.ini中去修改端口。
修改初始配置如下图所示,在PdBaseKits-tools-ini中,找到initialSysConfig方法可以看到初始配置。

initialSysConfig()#配置端口server = {'port' : 8062,}
(代码中初始化配置)
如果已经有了配置文件,在界面的系统设置中可以看到文件路径:


(config.ini)
-
配置路由
为了可以接收一个请求,我们需要配置我们的路由。如果你对路由没有概念,你可以把它认为就是服务器处理请求的入口。
-
路由前缀
这不是必须的,你可以复用我们的配置,但如果你希望修改的话,你可以在server-APP下server.py完成了服务器的启动配置。路由前缀就是请求“http://localhost:8062/v1/api/trigger/login”中的“/v1/api/trigger/”部分。

其中'prefix'定义了路由的前缀,可以根据你自己的业务需求进行修改,同时可以看到,刚刚修改的port最终在这里使用。
def register_blueprints(_app):from server.router import router_app.include_router(router.router, prefix="/v1/api/trigger")def run(host, port):_app = init_app()uvicorn.run(_app, port=port, host=host)
-
路由配置
为了让服务器可以处理我们的请求,我们需要配置我们的路由,在server-router目录下。

打开这个文件可以配置一个login请求处理,如下所示。
@router.post("/login", response_model=UserLoginResponse)async def login(body: User):return {"user": 'zyy', "id": "12", 'token': 'testteststesttest', 'nickname': 'dean', 'headUrl': 'i.png'}
将其设置为post请求,'/login'是路由,body是request,我们定义为User结构,response_model是响应的结构,定义为UserLoginResponse。我们将结构体的定义在schema.py中。

class User(BaseModel):user: strpwd: strclass UserLoginResponse(BaseModel):user: strid: inttoken: strnickname: strheadUrl: str
你可以根据自己的业务需求进行修改调整。
数据返回我们通过return完成,这需要保证返回JSON与response_model指定类型是一致的,否则会报错。
-
密码解密
我们配置了AES的加解密,我们默认你的登陆使用了AES进行加密,因此,我们需要先进行解密。
我习惯于将业务代码脱离router,因此,在我们的server-service下,我们可以写我们的业务代码。

在这里我新建了一个login方法,其对pwd进行解密。
class klingService:def login(self,userId, pwd):try:pwdDecrypt = aesECBDecrypt(pwd)except Exception as e:return Falseprint("pwdDecrypt:"+pwdDecrypt)#默认登陆成功return True
现在路由中的代码也需要引用这个login方法。
midService = klingService()logging.info("login ["+body.user+"],["+body.pwd+"]]")if midService.login(body.user, body.pwd):return {"user": 'zyy', "id": "12", 'token': "testtesttest", 'nickname': 'dean', 'headUrl': 'i.png'}else:return ""
和刚才的返回默认值相比,我们多了login的调用,但返回数据依然是模拟的。下一步我们将通过id,pwd去DB中校验,其相关的代码我们也会写到这个service中。
-
数据库访问
我们并没有像mybatis那样实现ORM,当然python也有自己的orm库,但我们并没有实现,这主要是因为我们的python应用,目前还没有需要大量的数据库访问,你可以自己去实现。相关代码在PdBaseKits-sql中。

DbBase.py实现了基础的连接和关闭,数据库的账号密码在config.ini中配置,我需要自建一个UserRegDao.py来实现用户表的读取,这个类需要继承DbBase类。在这里,我们需要自已来拼接一个SQL语句。
import loggingfrom typing import Unionfrom PdBaseKits.exceptions.exceptions import SqlConnectErrorfrom PdBaseKits.sql.DbBase import DbBasefrom entity.UserInfo import UserInfoclass UserRegDao(DbBase):def __init__(self):logging.info("UserRegDao")super().__init__()# 析构方法def __del__(self):super().__del__()def chkUserInfo(self, userName:str, pwd:str)->Union[UserInfo,bool]:sql = "select * from userinfo where username='"+userName+"' and password='"+pwd+"'"print(sql)data, c = self.exeStockSql(sql)if not data:return Falsefor r in data:id=r[0]userName = r[1]userInfo = UserInfo(id, userName)return userInfo
我们在这里创建了一个UserInfo类,用来承接用户信息数据:
class UserInfo():def __init__(self,id,user):self.id = idself.user = userid:intuser: str
然后,我们将这个dao层的调用写到service中,如下所示:
class klingService:def login(self,userId, pwd):try:pwdDecrypt = aesECBDecrypt(pwd)user = UserRegDao()except Exception as e:return Falseprint("pwdDecrypt:"+pwdDecrypt)return user.chkUserInfo(userId, pwdDecrypt)
我们看到,和之前相比,多了chkUserInfo()方法的调用。这样,我们就是真实的通过数据库来判断用户是否存在。
同时,我们的router中也可以获取用户信息了,我们需要改写一下,不再使用默认数据。
@router.post("/login", response_model=UserLoginResponse)async def login(body: User):midService = klingService()logging.info("login ["+body.user+"],["+body.pwd+"]]")userInfo = midService.login(body.user, body.pwd)if userInfo:return {"user": userInfo.user, "id": userInfo.id, 'token': "testtest"ken, 'nickname': 'dean', 'headUrl': 'i.png'}else:return ""
-
JWT生成token
在前面的代码中,我们只需要在router中login方法下,增加两行生成token的方法,并用这个真实生成的token去替代之前的“testtesttest”数据。
@router.post("/login", response_model=UserLoginResponse)async def login(body: User):midService = klingService()logging.info("login ["+body.user+"],["+body.pwd+"]]")userInfo = midService.login(body.user, body.pwd)if userInfo:accessTokenExpires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)accessToken = create_access_token(data={"userName": body.user,'id': userInfo.id}, expires_delta=accessTokenExpires)return {"user": userInfo.user, "id": userInfo.id, 'token': accessToken, 'nickname': 'dean', 'headUrl': 'i.png'}else:return ""
好了,我们的login到这里,已经从最初的返回一条默认数据,到现在完成了全部的功能。
-
运行
在完成router/service/UserRegDao后,打开serverMain.py文件,点击pyCharm右上角的运行当前文件,启动了我们的UI,然后点击“启动服务”按钮。在终端上看到如下提示说明启动成功!

我们通过apifox调试一下:
请求链接如下,这里的vi/api/trigger就是我们前文所说的前缀:
http://localhost:8062/v1/api/trigger/login
POST请求内容在body中,使用json:

然后发送请求:

完美!接口顺利运行,请求获得了响应!
-
总结
在今天的内容中,我们分享了使用PdServer实现了一个login接口。在这个过程中学习了使用数据库,解密,token生成等。整个过程十分简单,你只要按步骤一步一步来即可。如果你有任何的问题、建议,欢迎与我们联系。私信不经常看,欢迎直接加微信(cdszsz)!或关注公众号:AIGC中文站!认准咱们的头像。
2119

被折叠的 条评论
为什么被折叠?



