rust axum 如何实现SSO插件集成

在Rust的Axum框架中,如何实现SSO(单点登录)插件的集成?目前想在一个Axum项目中集成第三方SSO服务(比如OAuth2.0或SAML),但不太清楚具体步骤。是否需要引入特定的crate?如何配置路由和中间件来处理SSO的认证流程?能否提供一个简单的代码示例或最佳实践?

2 回复

使用axum实现SSO集成,可通过中间件实现。创建认证中间件,在请求处理前验证token或session。推荐使用axum的LayerService trait包装认证逻辑。可集成OAuth2、JWT等标准协议,通过tower中间件链处理认证流程。


在 Rust Axum 框架中实现 SSO(单点登录)插件集成,可以通过中间件和状态共享来实现。以下是核心实现方案:

1. 基础结构设计

use axum::{
    extract::{Request, State},
    middleware::{self, Next},
    response::{Response, Redirect},
    routing::get,
    Router,
};
use std::sync::Arc;

// SSO 配置
#[derive(Clone)]
pub struct SsoConfig {
    pub sso_server_url: String,
    pub client_id: String,
    pub client_secret: String,
    pub redirect_uri: String,
}

// 应用状态
#[derive(Clone)]
pub struct AppState {
    pub sso_config: SsoConfig,
    // 其他状态...
}

2. SSO 认证中间件

pub async fn sso_auth_middleware(
    State(state): State<Arc<AppState>>,
    mut request: Request,
    next: Next,
) -> Result<Response, Response> {
    // 检查会话或 Token
    if let Some(token) = extract_token(&request) {
        if validate_token(&token, &state.sso_config).await {
            return Ok(next.run(request).await);
        }
    }
    
    // 未认证,重定向到 SSO 登录页
    let login_url = format!(
        "{}/login?client_id={}&redirect_uri={}",
        state.sso_config.sso_server_url,
        state.sso_config.client_id,
        state.sso_config.redirect_uri
    );
    Err(Redirect::to(&login_url).into_response())
}

3. 回调处理端点

async fn sso_callback(
    State(state): State<Arc<AppState>>,
    query: axum::extract::Query<HashMap<String, String>>,
) -> Result<impl IntoResponse, impl IntoResponse> {
    let code = query.get("code").ok_or("Missing authorization code")?;
    
    // 使用 code 交换 token
    let token_response = exchange_code_for_token(code, &state.sso_config).await?;
    
    // 存储 token 到会话或 Cookie
    // 重定向到原始请求页面
    Ok(Redirect::to("/dashboard"))
}

4. 路由集成

pub fn create_app() -> Router {
    let state = Arc::new(AppState {
        sso_config: SsoConfig {
            sso_server_url: "https://sso.example.com".to_string(),
            client_id: "your_client_id".to_string(),
            client_secret: "your_secret".to_string(),
            redirect_uri: "https://yourapp.com/callback".to_string(),
        },
    });

    Router::new()
        .route("/", get(protected_handler))
        .route("/callback", get(sso_callback))
        .route_layer(middleware::from_fn_with_state(
            state.clone(),
            sso_auth_middleware,
        ))
        .with_state(state)
}

async fn protected_handler() -> &'static str {
    "这是受保护的页面"
}

5. Token 验证函数

async fn validate_token(token: &str, config: &SsoConfig) -> bool {
    // 调用 SSO 服务器验证 token
    // 返回验证结果
    true // 示例
}

async fn exchange_code_for_token(
    code: &str, 
    config: &SsoConfig
) -> Result<String, Box<dyn std::error::Error>> {
    // 实现 OAuth2 code 交换逻辑
    Ok("access_token".to_string())
}

使用方式

#[tokio::main]
async fn main() {
    let app = create_app();
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

关键要点

  1. 中间件模式:使用 Axum 中间件进行认证拦截
  2. 状态管理:通过 State 共享 SSO 配置
  3. OAuth2 流程:实现标准的授权码流程
  4. 错误处理:适当的错误处理和重定向
  5. 会话管理:需要结合会话存储(如 Redis)管理用户状态

这种设计可以灵活集成各种 SSO 提供商(如 Keycloak、Auth0 等),只需调整配置和验证逻辑即可。

回到顶部