报错内容
[{
"resource": "/e:/jsc-hi/Backend/src/auth.rs",
"owner": "rustc",
"code": {
"value": "Click for full compiler diagnostic",
"target": {
"$mid": 1,
"path": "/diagnostic message [0]",
"scheme": "rust-analyzer-diagnostics-view",
"query": "0",
"fragment": "file:///e%3A/jsc-hi/Backend/src/auth.rs"
}
},
"severity": 8,
"message": "method `from_request` has an incompatible type for trait\nexpected signature `fn(axum::http::Request<_>, &'life0 B) -> Pin<_>`\n found signature `fn(axum::http::Request<_>, &'life0 ()) -> Pin<_>`",
"source": "rustc",
"startLineNumber": 82,
"startColumn": 50,
"endLineNumber": 82,
"endColumn": 53,
"relatedInformation": [
{
"startLineNumber": 76,
"startColumn": 6,
"endLineNumber": 76,
"endColumn": 7,
"message": "expected this type parameter",
"resource": "/e:/jsc-hi/Backend/src/auth.rs"
},
{
"startLineNumber": 82,
"startColumn": 50,
"endLineNumber": 82,
"endColumn": 53,
"message": "change the parameter type to match the trait: `&'life0 B`",
"resource": "/e:/jsc-hi/Backend/src/auth.rs"
}
]
}]
// src/auth.rs jwt令牌,用户认证
use crate::auth;
use axum::body::Body;
use axum::http::header;
use axum::http::Request;
use axum::{
async_trait,
extract::FromRequest,
http::{Response, StatusCode},
response::IntoResponse,
};
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
use std::env;
// JWT生成函数:将生成JWT Token的逻辑封装成一个函数,包括设置Token的过期时间、加密算法等
pub fn generate_jwt(user: &AuthenticatedUser) -> Result<String, jsonwebtoken::errors::Error> {
let expiration = 3600; // 设置 token 过期时间为 1 小时,10000000000基本为长期
let claims = Claims {
sub: user.id.to_string(),
exp: expiration,
};
// 密钥管理:将从环境变量或配置文件中获取JWT密钥的逻辑封装成一个函数,以及密钥的安全管理。
let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); // 使用 env::var("JWT_SECRET") 从环境变量中获取 JWT 密钥,且环境变量不存在时返回自定义错误;
encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(secret.as_ref()),
)
}
//JWT验证函数:将验证JWT Token的逻辑封装成一个函数,包括解析Token并验证其有效性。
pub fn validate_jwt(token: &str) -> Result<auth::Claims, jsonwebtoken::errors::Error> {
let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
decode::<auth::Claims>(
token,
&DecodingKey::from_secret(secret.as_ref()),
&Validation::default(),
)
.map(|data| data.claims) // 直接返回Claims对象
}
// 错误处理:自定义错误类型,用于描述身份验证过程中,比如JWT生成、验证等可能发生的各种错误类型
#[derive(Debug)]
enum AuthError {
MissingHeader, // 缺少授权头部
InvalidToken, // Token无效或格式错误
DecodingError(String), // 解码错误,包含详细的错误信息
// 其他错误类型...
}
// 实现 `IntoResponse` 特征,使得 AuthError 可以被转换成 HTTP 响应,避免解析授权头部错误后没有后续响应导致程序 panic
impl IntoResponse for AuthError {
fn into_response(self) -> Response<Body> {
match self {
// 缺少头部或 Token 无效时,返回 401 未授权错误
AuthError::MissingHeader | AuthError::InvalidToken => {
StatusCode::UNAUTHORIZED.into_response()
}
// 解码出错时,返回包含错误信息的 401 未授权错误
AuthError::DecodingError(msg) => {
let body = format!("JWT Decoding Error: {}", msg);
Response::builder()
.status(StatusCode::UNAUTHORIZED)
.header(header::CONTENT_TYPE, "text/plain")
.body(Body::from(body))
.unwrap()
}
}
}
}
// 使用 `async_trait` 特征实现 `FromRequest`,用于从请求中异步提取 `AuthenticatedUser`
#[async_trait]
impl<B> FromRequest<B> for AuthenticatedUser
where
B: Send,
{
type Rejection = AuthError;
async fn from_request(req: Request<Body>, _: &()) -> Result<Self, Self::Rejection> {
// 尝试从请求头部获取 'Authorization' 字段
let authorization = req
.headers()
.get("Authorization")
.ok_or(AuthError::MissingHeader)?;
// 将头部的值转换为字符串,如果失败则返回 InvalidToken 错误
let token = authorization
.to_str()
.map_err(|_| AuthError::InvalidToken)?;
// 尝试从环境变量中获取 JWT 密钥,如果失败则返回 DecodingError
let secret = env::var("JWT_SECRET").map_err(|_| AuthError::DecodingError("JWT_SECRET must be set".to_string()))?;
// 使用提取的 Token 和密钥尝试解码 JWT
match decode::<Claims>(
token,
&DecodingKey::from_secret(secret.as_ref()),
&Validation::default(),
) {
Ok(decoded) => {
let user_id = decoded.claims.sub.parse::<i32>()
.map_err(|_| AuthError::DecodingError("Invalid user ID".to_string()))?;
Ok(AuthenticatedUser { id: user_id })
},
Err(e) => Err(AuthError::DecodingError(e.to_string())),
}
}
}
// 结构体定义
// 假设您有一个用户结构体
#[derive(Serialize, Deserialize)]
pub struct AuthenticatedUser {
pub id: i32,
// 可以添加其他对身份验证有用的字段,比如用户名、角色等
}
// 用户登录的声明:定义JWT的Claims结构体,用于描述Token中包含的声明
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
pub sub: String, // 由开发者自己定义的合法标识符
pub exp: i64, // 通常JWT Token中的过期时间(exp)应该是一个Unix时间戳
}
1
共 2 条评论, 1 页
评论区
写评论最后改为这样通过了,感谢
第二个参数()换成你定义的B
第二个参数()换成你定义的B