前一篇已经大致安装部署本地的open-webui的基础环境了,我们使用deepseek过程中,可能涉及到与已有系统的账号统一登录的情况。官方文档有一些关于如何对接的文档,稍显复杂,一时半会不太能掌握,自己就试着做一点简单的修改,实现一键登录需求。
大致思如如下:
A系统有test@email.com 的账号,在A系统页面增加一个按钮,自动登录到B系统;
B(open-webui)系统,前端通过url传递参数,然后提交到B系统后端;
B系统后端校验参数,识别到系统也存在test@email.com的账号,然后后端带着传递的参数请求A系统,
A系统校验参数合法,返回给B系统后端,
B系统后端接受到返回,如果校验无误,结果返回给B系统前端
B系统前端接收到后端返回结果,完成登录
大致流程如下:
作为示例,只做简单的md5校验
前端访问 http://127.0.0.1:8080/auth?token=c8da6b4e734be162&email=test@email.com
前端把 token和email两个参数传递到后端。
后端对email的md5值和token做比较完成用户的校验
这个是open-webui的标准登录页面。
我们参考这个页面的登录逻辑,做一下修改
前端部分
1 . 首先我们看下 open-webui/src/routes/auth/+page.svelte 文件
这个是前端的登录页,
关注下如下部分的代码
const signInHandler = async () => {
const sessionUser = await userSignIn(email, password).catch((error) => {
toast.error(`${error}`);
return null;
});await setSessionUser(sessionUser);
};
这个是用户登录的函数,
主要是通过userSignIn这个函数完成用的登录动作。
userSignIn函数在文件open-webui/src/lib/apis/auths/index.ts文件里实现的
export const userSignIn = async (email: string, password: string) => {
let error = null;const res = await fetch(`${WEBUI_API_BASE_URL}/auths/signin`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({
email: email,
password: password
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);error = err.detail;
return null;
});if (error) {
throw error;
}return res;
};
我们可以参考这部分代码,写出自己的实现如下:
在open-webui/src/routes/auth/+page.svelte文件增加如下代码
#自定义登录函数 const mySignIn = async () => { const params = new URLSearchParams(window.location.search); const token = params.get('token'); const email = params.get('email'); const sessionUser = await mySignIn (email, token).catch((error) => { return null; }); await setSessionUser(sessionUser); }; #从url里获取token、email两个参数,传递到函数userTokenSignIn里完成后台请求完成登录 #onMount增加我们的函数 onMount(async () => { await mySignIn (); ...... });
在open-webui/src/lib/apis/auths/index.ts文件参考userSignIn函数增加mySignIn 函数:
只需要修改后端请求的URL,其他部分都是照抄
export const mySignIn = async (email: string, token: string) => { let error = null; const res = await fetch(`${WEBUI_API_BASE_URL}/auths/mySignIn`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ email: email, token: token }) }) .then(async (res) => { if (!res.ok) throw await res.json(); return res.json(); }) .catch((err) => { error = err.detail; return null; }); if (error) { throw error; } return res; };
前端部分大部分已经完成。
后端部分
后端的登录在open-webui/backend/open_webui/routers/auths.py文件里面
首先看先之前的用户登录代码
############################
# SignIn
############################
@router.post("/signin", response_model=SessionUserResponse)
async def signin(request: Request, response: Response, form_data: SigninForm):......
user = Auths.authenticate_user(form_data.email.lower(), form_data.password)......
主要是通过SigninForm接受参数,
然后通过 Auths.authenticate_user实现email和password的校验
这个部分代码在 open-webui/backend/open_webui/models/auths.py里实现
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
log.info(f"authenticate_user: {email}")
try:
with get_db() as db:
auth = db.query(Auth).filter_by(email=email, active=True).first()
if auth:
if verify_password(password, auth.password):
user = Users.get_user_by_id(auth.id)
return user
else:
return None
else:
return None
except Exception:
return None
我们参考这两部分代码,不需要做太大的修改就可以实现我们的需求
在open-webui/backend/open_webui/routers/auths.py增加我们的实现mySignIn函数
只需要修改用户校验部分,其他部分都原封不动的照抄signin的函数
...... from open_webui.models.auths import ( AddUserForm, ApiKey, Auths, Token, LdapForm, SigninForm, MySigninForm, #引入自定义的表单接受 SigninResponse, SignupForm, UpdatePasswordForm, UpdateProfileForm, UserResponse, ) ############################ # mySignIn #form_data用的是自定义的 MySigninForm #用户验证用的是自定义的 authenticate_user_mySignIn ############################ @router.post("/mySignIn", response_model=SessionUserResponse) async def mySignIn(request: Request, response: Response, form_data: MySigninForm): ...... user = Auths.authenticate_user_mySignIn(form_data.email.lower(), form_data.token) ......
#自定义的函数最后一行,错误提示,也可以自定义下,
#不改也可以,就是报错情况下,提示的是用户名或者密码错误,有点不完美
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
增加自定义报错在文件open-webui/backend/open_webui/constants.py中修改
open-webui/backend/open_webui/models/auths.py里实现用户的校验函数
authenticate_user_mySignIn
还需要定义一个 MySigninForm 用于接受参数
import hashlib #需要用到计算md5 ...... #自定义接受参数 class MySigninForm(BaseModel): email: str token: str #自定义用户登录参数校验 def authenticate_user_mySignIn(self, email: str, token: str) -> Optional[UserModel]: try: with get_db() as db: auth = db.query(Auth).filter_by(email=email, active=True).first() if auth: #校验token,这里只简单的做md5的校验 md5hash = hashlib.md5(email.encode()) md5_token = md5hash.hexdigest() if token == md5_token: user = Users.get_user_by_id(auth.id) return user else: return None else: return None except Exception: return None ......
至此这个简单的校验email的md5值的token登录方式就实现了
我们访问地址
http://127.0.0.1:8080/auth?token=c8da6b4e734be162&email=test@email.com
如果token是email的md5值。就可以实现用户自动登录
chrome浏览器,打开开发者工具->网络->Fetch/XHR;检查是否完成
关于修改后的部署
如果你是通过docker部署的open-webui,代码修改后需要如下操作:
前端编译后会成才一个build的目录,覆盖到docker里原先的build目录;
----------前端覆盖docker的build文件夹操作-----------
1.压缩前端编译后的build文件夹 tar -czvf build.tar.gz ./build/ 2,压缩文件复制到docker并解压缩 #复制压缩文件到docker docker cp ./build.tar.gz open-webui:/app/backend/ #进入docker docker exec -it open-webui /bin/bash #返回docker根目录、移动压缩文件到根目录 cd ../ mv ./backend/build.tar.gz ./ #备份前端 mv build build_b #解压缩前端 tar -zxvf build.tar.gz ./
后端直接把修改的文件覆盖到docker里对应的文件;
然后重启docker。
最后总结下需要修改的几个文件
前端代码:
open-webui/src/routes/auth/+page.svelte
open-webui/src/lib/apis/auths/index.ts
后端代码:
open-webui/backend/open_webui/routers/auths.py
open-webui/backend/open_webui/models/auths.py
这4个文件修改就可以了。
---------------------------------------------------------------------------------------------
可以本地写一个python文件,用与生成email和token
def create_md5_token(email): md5hash = hashlib.md5(email.encode()) md5_token = md5hash.hexdigest() print("auth?token="+md5_token+"&email="+email) return md5_token emails = [ "a@test.com", "b@test.com", "c@test.com", "d@test.com", "e@test.com", "f@test.com", ] for email in emails: create_md5_token(email)
---------------------------------------------------------------------------------------------
后续发现,前端代码的修改直接放在
open-webuib/src/routes/+layout.svelte
里实现更好,同时需要增加setSessionUser函数。
---------------------------------------------------------------------------------------------
至此,可以把这个链接集成到原有的系统,实现单点登录。
token的加密方式可以更复杂一些,加入一些其他参数
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/9576.html 非本站原创文章欢迎转载,原创文章需保留本站地址!


休息一下~~