授权控制 #
角色管理 #
定义角色 #
rust
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Role {
Admin,
User,
Guest,
}
impl Role {
pub fn has_permission(&self, permission: &Permission) -> bool {
match self {
Role::Admin => true,
Role::User => matches!(
permission,
Permission::ReadOwn | Permission::WriteOwn
),
Role::Guest => matches!(permission, Permission::ReadOwn),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Permission {
ReadOwn,
WriteOwn,
ReadAll,
WriteAll,
Delete,
}
用户结构 #
rust
#[derive(Debug, Clone)]
pub struct AuthUser {
pub id: String,
pub role: Role,
}
impl AuthUser {
pub fn has_permission(&self, permission: &Permission) -> bool {
self.role.has_permission(permission)
}
}
授权中间件 #
rust
use actix_web::{dev::Payload, Error, FromRequest, HttpRequest};
use futures::future::{ready, Ready};
pub struct AuthorizedUser {
pub user: AuthUser,
}
impl FromRequest for AuthorizedUser {
type Error = Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
let user = req.extensions().get::<AuthUser>().cloned();
match user {
Some(user) => ready(Ok(AuthorizedUser { user })),
None => ready(Err(actix_web::error::ErrorUnauthorized("Unauthorized"))),
}
}
}
权限检查 #
手动检查 #
rust
#[actix_web::delete("/users/{id}")]
async fn delete_user(
path: web::Path<String>,
auth: AuthorizedUser,
) -> impl Responder {
if !auth.user.has_permission(&Permission::Delete) {
return HttpResponse::Forbidden().json(serde_json::json!({
"error": "Permission denied"
}));
}
HttpResponse::NoContent().finish()
}
自定义提取器 #
rust
pub struct AdminUser(pub AuthUser);
impl FromRequest for AdminUser {
type Error = Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
let user = req.extensions().get::<AuthUser>().cloned();
match user {
Some(user) if user.role == Role::Admin => ready(Ok(AdminUser(user))),
Some(_) => ready(Err(actix_web::error::ErrorForbidden("Admin access required"))),
None => ready(Err(actix_web::error::ErrorUnauthorized("Unauthorized"))),
}
}
}
#[actix_web::get("/admin/users")]
async fn list_all_users(_admin: AdminUser) -> impl Responder {
HttpResponse::Ok().json(serde_json::json!({ "users": [] }))
}
下一步 #
继续学习 CORS 跨域,了解跨域资源共享!
最后更新:2026-03-29