尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

零基础入门Python18|密码、认证、权限与接口测试基础

零基础入门Python18|密码、认证、权限与接口测试基础 零基础入门Python18密码、认证、权限与接口测试基础本篇图解程序执行顺序这张图对应代码的执行顺序。先说清输入、处理和输出再解释语法细节初学时不容易迷路。一、上一篇课后练习讲解订单状态应保留历史不建议直接删除。模型增加status取消函数先检查状态defcancel_order(db,order_id):orderdb.get(Order,order_id)iforderisNone:raiseValueError(订单不存在)iforder.statuscancelled:raiseValueError(订单已经取消)try:foriteminorder.items:item.product.stockitem.quantity order.statuscancelleddb.commit()db.refresh(order)returnorderexceptException:db.rollback()raise测试要在每个失败案例后重新查询数据库证明状态和库存没有被错误修改。可执行验收答案下面用 pytest 风格把三个边界固定下来deftest_cancel_success_restores_stock(client,db):ordercreate_order(db,statuspaid,items[(1,2)])responseclient.post(f/orders/{order.id}/cancel)assertresponse.status_code200assertdb.scalar(select status from orders where id?,(order.id,))cancelledassertdb.scalar(select stock from products where id1)order.stock_before2deftest_cancel_twice_does_not_add_stock(client,db):ordercreate_order(db,statuscancelled,items[(1,2)])beforedb.scalar(select stock from products where id1)responseclient.post(f/orders/{order.id}/cancel)assertresponse.status_codein(400,409)assertdb.scalar(select stock from products where id1)beforedeftest_password_never_in_response(client):responseclient.post(/register,json{email:aexample.com,password:secret123})assertpasswordnotinresponse.json()运行pytest -q时三个测试都通过如果取消接口返回 200 但库存未恢复检查事务是否在修改状态前读取了明细如果密码出现在响应或日志立即删除该字段并轮换测试凭据。二、本篇成果理解密码哈希、认证、授权、会话、Token和常见Web风险完成密码哈希与资源权限函数并用pytest验证成功和失败路径。安全不是最后上线前加一个开关而是每层明确不信任什么数据。三、密码绝不能明文保存错误user.passwordpassword123正确做法使用专门密码哈希算法。安装python-m pip installpwdlib[argon2]frompwdlibimportPasswordHash password_hashPasswordHash.recommended()stored_hashpassword_hash.hash(password123)assertstored_hash!password123assertpassword_hash.verify(password123,stored_hash)assertnotpassword_hash.verify(wrong,stored_hash)哈希不可逆验证不是加密后再解密。每个密码还会使用随机盐相同密码产生不同哈希。不要自己用普通SHA256保存密码它计算太快容易被暴力破解。四、认证与授权不同认证确认当前请求是谁授权确认这个用户能否执行某操作。用户登录成功不等于可以修改所有文章。资源必须检查owner_id。defensure_owner(current_user_id,resource_owner_id):ifcurrent_user_id!resource_owner_id:raisePermissionError(无权操作此资源)不要只在前端隐藏按钮攻击者可以直接发送HTTP请求后端必须检查。五、会话和TokenCookie会话常在服务端保存登录状态浏览器携带会话Cookie。JWT Token把签名声明交给客户端携带服务器验证签名和过期时间。无论采用哪种方式都要考虑HTTPS传输过期时间退出和撤销密钥管理Cookie的HttpOnly、Secure和SameSiteToken不能放进URL或日志。后续Flask项目使用会话FastAPI项目使用OAuth2和JWT便于比较。六、参数化查询、XSS、CSRF和CORSSQL注入使用参数化查询或ORM不拼接输入XSS输出到HTML时转义富文本需要白名单清洗CSRFCookie自动携带时写操作使用CSRF Token或SameSite策略CORS限制哪些浏览器来源可跨域调用不是身份认证限流限制登录和高成本接口请求频率错误提示登录失败统一提示“邮箱或密码错误”避免枚举账号。不同风险需要不同措施不能用JWT解决所有安全问题。七、可测试的权限服务security.pyfromdataclassesimportdataclassfrompwdlibimportPasswordHash password_hashPasswordHash.recommended()dataclassclassUser:id:intemail:strpassword_hash:strdataclassclassArticle:id:inttitle:strauthor_id:intdefregister_user(user_id,email,password):emailemail.strip().lower()ifnotinemail:raiseValueError(邮箱格式不正确)iflen(password)8:raiseValueError(密码至少8位)returnUser(iduser_id,emailemail,password_hashpassword_hash.hash(password),)defauthenticate(user,password):returnpassword_hash.verify(password,user.password_hash)defupdate_article(article,current_user,new_title):ifarticle.author_id!current_user.id:raisePermissionError(只能修改自己的文章)new_titlenew_title.strip()ifnotnew_title:raiseValueError(标题不能为空)article.titlenew_titlereturnarticletest_security.pyimportpytestfromsecurityimportArticle,authenticate,register_user,update_articledeftest_password_is_hashed_and_can_be_verified():userregister_user(1,Aliceexample.com,password123)assertuser.emailaliceexample.comassertuser.password_hash!password123assertauthenticate(user,password123)assertnotauthenticate(user,wrong)deftest_only_author_can_update_article():authorregister_user(1,aexample.com,password123)otherregister_user(2,bexample.com,password123)articleArticle(id1,title旧标题,author_idauthor.id)updatedupdate_article(article,author,新标题)assertupdated.title新标题withpytest.raises(PermissionError,match只能修改自己的文章):update_article(article,other,恶意修改)assertarticle.title新标题deftest_invalid_registration():withpytest.raises(ValueError,match邮箱):register_user(1,invalid,password123)withpytest.raises(ValueError,match至少8位):register_user(1,aexample.com,short)运行pytest-q测试不是只覆盖成功路径。权限测试还要确认失败后原文章没有被修改。八、项目进入框架前的安全清单密码只保存专用哈希密钥和数据库密码来自环境变量每个资源操作检查当前用户查询参数化错误信息不泄露账号状态和堆栈登录、上传和AI接口有限流计划自动化测试包含未登录、无权限、重复数据和非法输入。九、本篇验收能解释哈希与加密区别能区分认证和授权密码验证代码真实运行非作者修改被拒绝且数据不变能说明XSS、CSRF、CORS处理不同风险pytest覆盖成功和失败路径。十、课后练习给权限服务增加delete_article和管理员角色admin可删除任意文章普通用户只能删除自己的文章。编写作者删除成功、其他用户失败、管理员成功三个测试。下一篇开始Flask完整记账项目并把会话认证、数据库和测试串联起来。实战补充第一个可回归的后端测试集测试应该描述用户能观察到的行为而不是 ORM 私有属性。最小测试集包含成功、输入错误、资源不存在、越权和事务回滚。deftest_create_task(client):responseclient.post(/tasks,json{title:学习 SQL})assertresponse.status_code201assertresponse.json()[data][title]学习 SQLdeftest_empty_title(client):responseclient.post(/tasks,json{title:})assertresponse.status_code422数据库使用临时库或事务回滚外部 Redis 用假实现测试结束后清理文件和依赖替换。下一篇开始 Flask 账本项目先创建应用工厂和健康检查。本篇结束完整模块文件本节不是代码片段而是本篇结束时该模块的完整版本。请先备份旧文件再整体替换替换后重新运行本篇命令和测试。阅读时重点看本篇新增的函数、事务边界和错误处理未涉及的代码先不要自行删减。本篇完整示例fromgetpassimportgetpassfromhashlibimportscryptfromosimporturandom salturandom(16)digestscrypt(getpass(密码).encode(),saltsalt,n2**14,r8,p1)print(digest.hex())
返回列表