客户端是不是应该在每条路由上进行身份验证? [关闭]

Posted

技术标签:

【中文标题】客户端是不是应该在每条路由上进行身份验证? [关闭]【英文标题】:Should the client authenticate on every route? [closed]客户端是否应该在每条路由上进行身份验证? [关闭] 【发布时间】:2020-11-16 02:35:50 【问题描述】:

localStorage 中有一个 JWT。

假设用户转到app.com/accounts

JWT 被发送到后端app.com/api/accounts 获取数据,在到达之前,它会在身份验证中间件中进行检查。

后端

let authenticationMiddlewareBackend = (req, res, next) => 
    let token = req.headers.authorization;
    jwt.verify(token, "secret", (err, decoded) => 
        if (err) 
            res.status(401)
         else 
            req.decoded = decoded;
            next();
        
    );
;

app.all("/api/*", authenticationMiddlewareBackend);

现在可以了。问题是,客户端是否应该在到达app.com/accounts 之前也这样做?

客户

async function authenticationMiddlewareClient(next) 
    if (window.location.pathname != "/login") 
        let verifyResponse = await (
            await fetch(`/verify`, 
                method: "GET",
                withCredentials: true,
                credentials: "include",
                headers: 
                    Authorization: localStorage.getItem("token"),
                    Accept: "application/json",
                    "Content-type": "application/json",
                ,
            )
        ).json();

        if (verifyResponse.isAuthenticated) 
            next();
         else 
            page("/login");
        
     else 
        next();
    


page("*", authenticationMiddlewareClient);

后端

router.get("/verify", async function (req, res) 
    try 
        let token = req.headers.authorization;
        jwt.verify(token, "secret", (err, decoded) => 
            if (err) 
                res.status(401)
             else 
                res.status(200).send( isAuthenticated: true, ...decoded );
            
        );
     catch (err) 
        next(err);
    
);

客户端是否应该将身份验证结果存储在一个变量中,而不是每次都发出验证请求?我不确定这是否可以被某种方式利用。

【问题讨论】:

我不认为每次都需要它。当经过身份验证的请求因 401 错误而失败时,前端可以理解令牌无效/过期,然后删除令牌。所以,我认为不需要每次都验证。 我不太明白你的意思。你能澄清一下吗?我仍然需要每次发送请求以检查有效性。 我的意思是,登录时生成的令牌可能会存储在本地存储中,无需验证即可用于后续结果。 (在第一页加载时验证它可能是个好主意)。之后无需再次验证令牌,因为如果任何其他请求失败,玩具将收到 401 错误。因此,如果出现 401 错误,请从本地存储中删除令牌并将用户重定向到登录页面。 我明白了。我的困惑是,如果有人放置具有isAuthenticated: true 属性的虚构令牌,他们就可以访问该应用程序。另外,我怎么知道这是第一个页面加载? 即使他们添加了一个伪造的令牌,他们也无法进行任何操作,对吧。此外,当他们尝试执行操作(向后端发出请求)时,您会将他们重定向到登录,因为假令牌被后端发现并发送 401 【参考方案1】:

最好在 App 加载时检查令牌,而不是在每个路由器上检查。 Token 会被后端 API 检查,你可以通过检查状态码是否为 401 来验证。

【讨论】:

【参考方案2】:

不需要单独的 API 调用,因为它不会为流程增加任何安全性或效率。只需在处理任何数据之前检查中间件中的 JWT,就像您在第一个文件中所做的那样。

【讨论】:

跟进:为什么您认为可能需要单独进行? 我不知道。我不知道如何限制对应用程序本身的访问。我应该在渲染路由之前检查 isAuthenticated 布尔值的令牌内容吗?是什么阻止了某人将假令牌放入 localStorage 以获取应用程序的访问权限? 如果令牌是假的,那么你的中间件就会知道。你有一个秘密,没有人知道(希望如此),所以他们无法生成符合你秘密的明智 JWT 这是我的问题。 “如果令牌是假的,那么你的中间件会知道。” 是说我仍然需要向/verify后端路由发出请求以检查有效性,这就是我正在做的事情.令牌只是base64,中间部分可以伪造,因为客户端没有办法检查有效性,每次需要路由时都没有请求。 不,但是中间件会处理这个,所以你不需要在单独的调用中这样做。如果用户想要... 发布图片,但需要登录:他们发布图片,负载中包含 JWT,以便后端可以读取它,验证用户的授权,然后将图片发送到该过程的下一部分。如果您在单独的调用中执行此操作,则用户可以简单地在客户端伪造“成功”部分,因此最好在中间件中执行此操作。

以上是关于客户端是不是应该在每条路由上进行身份验证? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C# SMTP 无法在 Outlook.com 端口 587 上进行身份验证。“服务器响应为:5.7.1 客户端未通过身份验证”

无法在 Chargify REST API 上进行身份验证

静默刷新在 OPTIONS 预检上进行身份验证,但不在 GET 到 UserInfo 端点上进行身份验证

Http客户端。在自动发现的代理上进行身份验证的默认凭据

通过 SSH 隧道在 PostgreSQL 上进行身份验证失败

在 Glassfish 上进行领域身份验证后重定向