fastapi开发api确实fast.东西开发完了,前后端调试也方便,要上线了,怎么保证接口文档不被非法访问呢?简单想了几个场景
内网部署
将swagger的入口监听在内网,域名访问的话,也直接解析成内网,外网不能访问也是个不错的选择.
直接关闭
这招算是釜底抽薪了,直接关门,咱都不访问.算是最简单有效的办法.
代码
app = FastAPI(
docs_url=None,
redoc_url=None
)
动态开关
默认关闭,确实有需要查看,临时打开,用完关闭,也是个不错的选择.
原理就是:访问/docs时,默认没有,通过另一个接口临时调整一个参数,这时才允许访问.
主要代码
app = FastAPI(
docs_url=None,
redoc_url=None
)
@app.get('/add_docs')
def show_docs_by_manager():
logger.info(app.docs_url)
msg = 'ok'
if app.docs_url is None:
app.docs_url = '/docs'
msg = 'docs is open !'
else:
app.docs_url = None
msg = 'docs is disabled !'
logger.info(app.docs_url)
return response_struct(msg=msg)
@app.get("/docs")
async def get_documentation():
if app.docs_url is None:
return response_struct()
else:
return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")
如上,需要访问时,直接/add_docs接口,也不添加参数了,访问一次打开,再访问一次关闭,这样就实现了动态开关的目的.
开启basic auth
出发点就是访问/docs时进行一次用户名和密码认证,用nginx的话很容易实现
示例代码
echo "username:$(openssl passwd -crypt 'password')" >> /home/.htpasswd
location /docs {
auth_basic "请输入密码";
auth_basic_user_file /etc/apache2/.htpasswd;
}
既然nginx能实现,我牛掰fastapi自然也可以.
代码
from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.status import HTTP_401_UNAUTHORIZED
from fastapi.openapi.docs import get_swagger_ui_html
app = FastAPI(
docs_url=None
)
security = HTTPBasic()
@app.get("/docs",include_in_schema=False)
async def get_documentation(credentials: HTTPBasicCredentials = Depends(security)):
if credentials.username != "rainbird" or credentials.password != "pwd":
raise HTTPException(
status_code=HTTP_401_UNAUTHORIZED,
detail="Incorrect email or password",
headers={"WWW-Authenticate": "Basic"},
)
else:
return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")
如上,访问/docs需要验证,用户名是rainbird,密码是pwd
结尾
本文只是简单的示范了swagger的页面安全问题.对于后端接口,内部访问的话最好就是直接放内网,也不需要加密和认证,性能会好一些.如果接口一定要放公网的话,除了考虑好swagger的安全,还要处理好接口的访问权限,切莫要门户大开,锁都不加.