rocket-FromRequest-cookie-login

Rocket利用cookie实现登陆功能

头像
逆旅 2022-08-07T08:59:09

1.具体逻辑流程

st=>start: 登陆 cond=>condition: 验证cookie是否存在 Yes or No? op1=>operation: 提交用户信息 op2=>operation: 把用户id加密储存在cookie op3=>operation: 计算位移 op4=>operation: 模拟人工滑动 e=>end: 管理后台 st->cond->op1->op2->e cond(no)->op1 cond(yes)->e

2.FromRequest功能

原文介绍:A request guard is a type that represents an arbitrary validation policy. The validation policy is implemented through FromRequest. In other words, every type that implements FromRequest is a request guard.
Request guards appear as inputs to handlers. An arbitrary number of request guards can appear as arguments in a route handler. Rocket will automatically invoke the FromRequest implementation for request guards before calling the handler. Rocket only dispatches requests to a handler when all of its guards pass.

我们可以通过FromRequest在http请求之前进行操作,包括验证cookie,类似于Flask中路由函数实现的 @login_required 装饰。

3.具体代码

auth.rs

/*
权限验证工具,验证是否登陆;
利用FromRequest请求守卫,获取cookie的login_status;
*/

use rocket::{request::{FromRequest, self, Outcome}, Request, http::Status};
use serde::Deserialize;


#[derive(Debug, Clone, Deserialize)]
pub struct UserAuth{
    permissions: String
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for UserAuth {
    type Error = ();

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
        let cookies = req.cookies();
        let cookie_value = cookies.get_private("login_user_id");
        let status = match cookie_value {
            Some(_) => true,
            None => false,
        };
        if status {
            return Outcome::Success(UserAuth{ permissions:String::from("admin") }) ;
        }else {
            return Outcome::Failure((Status::Unauthorized,()));
        }
    }
}

login.rs

use crate::models::user::User;
use crate::utils::response::HandleResponse;
use rocket::http::{Cookie, CookieJar};
use rocket::response::Redirect;
use rocket::route;
use rocket::serde::json::Json;
use rocket::serde::json::Value;
use rocket_dyn_templates::Template;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[route(GET, uri = "/login")]
pub async fn index(cookies: &CookieJar<'_>) -> HandleResponse {
    let mut context = HashMap::new();
    let login = cookies.get_private("login_user_id");
    let login_status = match login {
        Some(_) => true,
        None => false,
    };
    context.insert("users", "users");
    if login_status {
        return HandleResponse::Redirect(Redirect::to("/admin/dashboard"));
    } else {
        return HandleResponse::Template(Template::render("content/login", context));
    };
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct LoginUser {
    mail: String,
    password: String,
    remember: bool,
}

#[route(POST, uri = "/login", data = "<form_data>")]
pub async fn post(cookies: &CookieJar<'_>, form_data: Json<LoginUser>) -> Value {
    let user_data = form_data.into_inner();
    let info = User::login_blog(&user_data.mail, &user_data.password).await;
    let login = info.get("status").clone().unwrap().as_str().unwrap();
    if login == "success" {
        let user = User::get_user_by_email(&user_data.mail).await;
        let mut ck = Cookie::new("login_user_id", user.id.unwrap().to_string());
        if !user_data.remember {
            ck.set_expires(None);
        };
        cookies.add_private(ck);
    };
    return info;
}

admin.rs

#[get("/dashboard")]
pub async fn index( _user_auth: UserAuth, ) -> Template {
 /*
具体逻辑代码,管理员
*/
    let template = Template::render("admin/blog-dashboard", &context);
    template
}
最后修改: 2022-08-07T09:36:12

版权声明:署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)

comment 评论

验证图片
评论
仿 Valine