关于日志流量监控预警小小项目 | 对数据库的管理工具:migrate

manage.py的具体内容:

#命令行管理flask

#flask_script  flask的命令行管理工具

#安装   pip  install flask_script

# 首先,创建一个Python模板运行命令脚本,可起名为manager.py;

# 在该文件中,必须有一个Manager实例,Manager类追踪所有在命令行中调用的命令和处理过程的调用运行情况;

# Manager只有一个参数——Flask实例,也可以是一个函数或其他的返回Flask实例;

# 调用manager.run()启动Manager实例接收命令行中的命令;

from flask_script import Manager

from flask_migrate import Migrate, MigrateCommand

from model import db

from app import create_app

app = create_app()

manager = Manager(app)

#创建db管理工具

migrate = Migrate()#实例化一个migrate对象

migrate.init_app(app,db)#把db和app都和migrate绑定在一起

#添加迁移命令到manager中(manage是命令行管理工具)

#(db是只是一个名字,可以不叫db)

#(然后只要有这行命令 python manage.py --help就会出现新的属性db

#(表示把MigrateCommand命令添加到db命令子集下面去)

#于是我们就可以通过python manage.py db 来管理运行manager命令了

manager.add_command('db', MigrateCommand)

if __name__ == "__main__":

    manager.run()

#初始化migration仓库(第一次创建migrations目录的时候使用)

# python manage.py db init

#提交版本变更

#python manage.py db migrate

#生效数据库

#python manage.py db upgrade

#python manage.py

对数据库的操作:

对数据库的管理工具:migrate

我们这个项目内容简单 但是所用的库很多 面试的时候可以提及

内容单一的原因:还在完善 使用过什么功能 做过什么

from datetime import datetime

from sqlalchemy import Column,Integer,String,DateTime

add_time=db.Column(db.DateTime,default=datetime.now)

在数据库里面添加一列时间,给的类型是类型,里面默认值是当前时间

python manage.py runserver :

-d:开启debug模式

-D:关闭debug模式

在代码里面临时新增一列属性,数据库不会自动新增

线上环境顶多对于数据库就查询和插入,而不是所有人都可以拥有所有权限(db.create_all只适用于测试环境,只能在没有这张表,创建的时候才生效,而创建好了之后再修改orm映射关系里的任何东西并不会变化)所以新添加字段就在创建新表的时候才添加

高级dba有时候比开发工资都高

对数据库敬畏

数据量比较大 我们一般是备份 而不是回收站(回收站没啥必要)

而我们会借助一个新的工具migrate:只要表的结构任意一个地方改了 就会同步生效到数据库里面去

这是在命令行管理工具里面做的 所以我们要写道manage里面去

首先在命令行先安装flask-migrate(要下载2.5.3版本)

在manage.py里面添加:from flask_migrate import Migrate, MigrateCommand

我们现在创建的模型都是基于db的

怎么生效数据库修改呢?

先初始化migration仓库(只要做一次就好 第一次创建migrations目录的时候使用)

 python manager.py db init

然后我们的目录里面会自动创建新出现一个文件夹migrations作为仓库

然后提交版本变更(生效版本号)python manage.py db migrate(实质就是判定它需要生效哪些东西)

生成版本号在仓库目录里面就会有一个versions  里面存放着每次提交要做的语句 提交一次就会有一个版本号

然后生效数据库

python manage.py db upgrade就是把这个刷新到数据库里面 就可以看到修改生效(其实就是执行新的版本脚本)

而生效到数据库后 数据库里也自动生成了一张表(alembic_version)这张表里面记录的也就是版本号(这里的版本号和你目录里面的是一致的才能提交成功 否则会提交失败)

所以如果版本不一致了 就把目录和表都删掉  重新init

设计数据模型(数据库):

也就是orm层的关系映射

我们现在再创建一个班级表与学生表关联:

创建表的时候如果不指定tablename就会自动把你的类名小写

需要在学生那边添加班级id字段 于是我们要添加外键约束(我们添加的外键在那个表里面得是主键) 不能随意添加了

在sutdent里添加:(这个对象属性里面多了一个stuclass属性)

class_id=db.Column(db.ForeignKey('stuclass.class_id'))

(#外键约束 这个class_id只能写入stuclass.class_id里有的元素)

在stuclass里面添加:(属性多了stuinfo属性 这个属性里面就包含这这个班级里面有哪些学生对象  不需要sql联表查询了 )

stuinfo=db.relationship("Student",backref="stuclass")

(#关联两个数据模型 并且为student模型创建反向查询字段stuclass)

这一行是给stuclass创建与student的关系 然后给stuclass创建了一个stuinfo属性 里面包含着这个班级的学生对象  backref是设置反向查询字段  也就是在student那边创建了一个stuclass属性 里面包含着你所在的班级对象 这样两张表可以相互查找对象 访问对象的属性直接用点去访问就好了

db.Column是创建字段 生效到数据库

db.relationship是创建orm关系 创建关系其实也就是创建属性 只生效到orm

基于外键约束才能创建关系 会自动识别关联到外键 否则两张毫无关联的表不能做关联

认证:

常见的认证方式:基于http基本认证去做的

认证都放在libs里面的authorize 去做一个权限的管理

认证是基于http基本认证去做的

http协议支持两种认证方式:基本认证和摘要认证

没有绝对安全的认证

http基本认证:发起请求的时候 携带一个头部字段(里面包含用户名和密码)

在postman里面点击Authorization 选择basic auth(基本认证) 表示选择认证方式为基本认证 然后填写用户名密码 于是在headers里面就可以看到一个Athorization里面带有basic base34(username:password)这个格式不能变 其中选择基本认证的话 会是basic  然后base64是网页的编码方式 说明这是把用户名和密码经过base64加密之后放入athorzation的头部字段里面

在postman的右上角里面有个code按钮 按进去 这个code的意思就是实现这个请求用代码怎么实现  代码里面athorization所带的就是经过base64加密的用户名密码 这是客户端要做的事情

服务端就是拿到这个加密后的用户名密码 然后解密 然后响应

api授权认证:

只能拿到权限之后才能调用api

这是基于http基本认证去做的

在libs文件夹里面先加入一个文件 authorize.py

from flask_httpauth import HTTPBasicAuth

from  flask import request

auth=HTTPBasicAuth()

#当执行auth.login_required时,会执行auth,verify_password对应的函数

#这个函数返回为真就表示认证成功,返回为假就表示认证失败

@auth.verify_password

def verify_password(token,password):#这两参数名字随便定 前面时用户名 后面是密码

    #支持多种认证方式

    if token and password:

#如果authorization头部字段里传了用户名和密码过来就认证成功

        return True

    elif token and token =="api":

#authorization:basic base64(api:)才进行api授权

        return api_authorize()

def api_authorize():

    params=request.args #获得url后面的参数

    appid=request.get("appid")

    passwd=request.get("passwd")

    if appid=="root" and passwd=="123456":

        return True

    return False

所以只能在url?

然后在相应的api文件里面导入 from libs.authorize import auth

然后在需要认证的地方加一个装饰器@auth.login_required

这样加上装饰器之后是需要认证之后才能请求

192.168.0.105:8000/v1/monitor?appid=root&passwd=123456这样就能get到数据表里面的内容

浏览器有登录弹窗出来一般都是基本认证

401代表就是认证失败

要做api授权的表

##############

#API授权表的模型

#多对多的关系

app_permission = db.Table("app_permission",

                          db.Column("api_id",db.ForeignKey("api_token.id")),

                          db.Column("permission_id",db.ForeignKey("api_permission.id"))

                          )

# api_token表

#存放的是授权密钥,以及授权id

class ApiToken(db.Model):

    __tablename__ = "api_token"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    appid = db.Column(db.String(128), nullable=False)

    secretkey = db.Column(db.String(128), nullable=False)

    #通过中间表去创建多对多的关系

    manage = db.relationship("ApiPermission", secondary=app_permission, backref="token")

#存放的是授权的url

class ApiPermission(db.Model):

    __tablename__ = "api_permission"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    url = db.Column(db.String(128), nullable=False)

    method_type = db.Column(db.String(128), nullable=False)

#监控项数据模型

#id

#user_id

#prov

#isp

#bd

#实现restful api接口的增删改查

说明是把每个用户申请表的权限存入这张表 然后用户要携带这个表里面的信息去查询此表 如果表里能够查询到则代表有权限 没有查询到则代表没有权限

然后我们添加完这段代码把它生效到数据库里面 我们多了三张表

两个表是多对多的关系:

一个是员工表   而一个是业务表

一个人负责好几个业务 而一个业务好几个人负责

于是我们会创建一个中间表来维持多对多的关系 中间表的维持内容就是员工id以及业务id  然后会把每一条都计入中间表 如1-3,1-2,2-1,2-3等来表明多对多的关系 而中间表里面的员工id就外键到员工表里面  业务id就外键到业务表里面

 

Authorize.py里面的内容

#基于  http基本认证

#api授权认证

from flask_httpauth import HTTPBasicAuth

from flask import request

from model.student import ApiToken

from hashlib import md5

auth = HTTPBasicAuth()

#当执行auth.login_required时,会执行auth.verify_password对应的函数,

#这个函数返回为真就表示认证成功,返回为假就表示认证失败

@auth.verify_password

def verify_password(token, password):

    #支持多种认证方式

    if token and password:

        #如果authorization头部字段里传了用户名和密码过来就认证成功

        return True

    elif token and token == "api":

        #authorization: basic base64(api:)

        return api_authorize()

#签名认证

#1、接口方提供出appid和secretkey

#2、调用方根据appid和secretkey,按照一定的算法生成sign

#3、接口方来验证签名

def api_authorize():

    params = request.args

    # 我们需要客户端传递过来的这三个参数来对你进行认证

    appid = params.get("appid")

    # 盐值就是为了防止你的密码被轻易推导出来 于是给它加一段随机的字符串 这样就不会被推导出来

    salt = params.get("salt") #盐值

    sign = params.get("sign") #签名

    api_token = ApiToken.query.filter_by(appid = appid).first()

    if not api_token:

        return False

    #验证有没有此url和方法的权限

    # 这一步是判断你所携带的url和方法是否有权限

    # api_token 刚刚得到的对象   request.path 这是request请求过来的url路径

    # request.method.lower()   request方法进行小写的转换

    if not has_permission(api_token, request.path, request.method.lower()):

        return False

    #获取数据库里的密钥 密钥只有天知地知你知我知 第三方不知

    secretkey = api_token.secretkey

    #生成服务端的签名

    #可以加上时间戳来防止签名被别人盗取,重复访问

    user_sign = appid + salt + secretkey

    m1 = md5() #所以这样在网络端传输的都是密文 不会泄漏密码

    m1.update(user_sign.encode(encoding="utf-8"))

    #判断客户端传递过来的签名和服务端生成签名是否一致

    # 所以客户端和服务端的签名加密方式要是一模一样的才行

    # 这就是前面认证

    if sign != m1.hexdigest():

        return False

    else:

        return True

#url验证

def has_permission(api_token, url, method):

    #客户端请求的方法和url

    mypermission = method+url

    #获取此api_token对象的所有url权限

    all_permission = [permission.method_type+permission.url

                      for permission in api_token.manage]

    if mypermission in all_permission:

        return True

    else:

        return False

签名认证的缺点:容易被人获取到  于是可以在签名里面添加一个时间戳(规定半个小时之后就不能获取数据了) 每一次请求的时候都会携带新的时间戳来请求

我们只要运行manage.py 或者server.py  其他都被导入运行

运行是按模块去运行的 只要导入 整个模块都会运行 (模块是最小运行单位)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值