You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

登录成功后无法从Actix Web会话中获取user_id的问题

问题:Actix Web会话中无法在中间件获取用户ID

编辑补充:
最初我使用的是CookieSession。在看到Đorđe的评论后,我决定切换为Redis处理会话。在GPT的帮助下,Redis的配置过程很顺利,现在会话可以持久化存储了。

原问题内容

我正在学习Rust,并基于Actix Web开发一个项目。我已经实现了登录系统并配置了登录认证中间件。提交登录请求后,用户ID会传递到浏览器并存储在Cookie中,在站内页面跳转时能维持该用户ID,但登录成功后却无法从会话数据中获取用户ID。

登录接口代码

#[post("/login")]
async fn login_submit(
    pool: web::Data<PgPool>,
    form_data: Form<LoginFormData>,
    session: actix_session::Session,
) -> Result<impl Responder, WrappedError> {
    let user = match db::get_user_by_email(&pool, &form_data.email).await {
        Ok(user) => user,
        Err(_) => return Err(WrappedError(anyhow!("Invalid email or password"))),
    };

    let password_hash = PasswordHash::new(&user.password_hash)
        .map_err(|_| WrappedError(anyhow!("Invalid password hash")))?;

    let argon2 = Argon2::default();

    let password_verified = argon2
        .verify_password(form_data.password.as_bytes(), &password_hash)
        .is_ok();

    println!("Password verified: {}", password_verified);
    println!("Stored hashed password: {}", user.password_hash);

    if password_verified {
        session
            .insert("user_id", user.id)
            .map_err(|e| WrappedError(anyhow!("Session error: {}", e)))?;
        println!("Session set with user_id: {}", user.id);
    
        // Add these lines to print the user_id from the session after setting it
        match session.get::<i32>("user_id") {
            Ok(Some(user_id)) => println!("User id in session after setting: {}", user_id),
            Ok(None) => println!("User id not found in session after setting"),
            Err(e) => println!("Error getting user id from session after setting: {}", e),
        }
    
        let response = HttpResponse::Found().append_header(("location", "/")).finish();
        Ok(response)
    } else {
        Err(WrappedError(anyhow!("Invalid email or password")))
    }
}

中间件代码

然而,当我尝试在中间件中获取用户ID时,得到的结果是None。以下是我的中间件代码:

impl<S> Service<ServiceRequest> for UserLoginStatusMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<EitherBody<BoxBody>>, Error = Error>,
    S::Future: 'static,
{
    type Response = ServiceResponse<EitherBody<BoxBody>>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

    forward_ready!(service);

    fn call(&self, req: ServiceRequest) -> Self::Future {
        let session = req.get_session();
        let user_id: Option<i32> = session.get("user_id").unwrap_or(None);
        let user_logged_in = user_id.is_some();

        println!("UserLoginStatusMiddleware user_id: {:?}", user_id);
        println!("UserLoginStatusMiddleware user_logged_in: {}", user_logged_in);
        println!("UserLoginStatusMiddleware session cookie: {:?}", req.cookie("my_session"));
        println!("UserLoginStatusMiddleware request headers: {:?}", req.headers());

        req.extensions_mut().insert(user_logged_in);

        let fut = self.service.call(req);
        Box::pin(async move {
            let res = fut.await?;
            Ok(res)
        })
    }
}

疑问与应用配置

在中间件中,我尝试使用session.get("user_id").unwrap_or(None)来获取用户ID,但这似乎不起作用。这种方法是否存在问题,或者有没有其他从会话中获取用户ID的方式?

我的代码编译没有错误。

应用注册代码如下:

App::new()
            .wrap(
                CookieSession::signed(&[0; 32])
                    .secure(false)
                    .name("my_session")
                    .path("/")
                    .http_only(true)
            )
            .wrap(UserLoginStatus)
...

内容的提问来源于stack exchange,提问作者rc_tn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:34:58