尝试使用 express-jwt 阻止访问除登录页面以外的 Angular 应用程序时出现问题

Posted

技术标签:

【中文标题】尝试使用 express-jwt 阻止访问除登录页面以外的 Angular 应用程序时出现问题【英文标题】:Issue when trying to prevent access to an angular application except the login page, using express-jwt 【发布时间】:2018-05-27 03:05:27 【问题描述】:

我有一个 angular + express 应用程序。我想阻止访问角度应用程序,除非用户经过身份验证。为此,我使用 jwt 检查用户是否可以访问内容,除非该页面是登录页面,在这种情况下,任何人都可以访问它。

它在“阻止访问”方面工作正常:如果我尝试不使用令牌进行访问,我会收到一条消息,指出令牌无效。如果我尝试使用令牌访问,我会看到 Angular 应用程序。

它不起作用的地方是“除非”部分:如果我尝试访问/dist/login,我会得到一个空白页。原因是服务器发送了以下文件(这是我的 Angular 应用程序的文件):

index.html main.738685558cc44b584d9e.bundle.js 其他 .js 文件... styles.8ebd0fc21ad0f11c194c.bundle.css

但是虽然index.html 的内容是正确的,但其他文件都具有相同的错误内容,这是一个错误:invalid token...。 Angular 应用程序无法加载,因为 .js 文件不正确,我无法访问我的登录页面,从而阻止任何人访问 Angular 应用程序(除非手动设置令牌)。

为什么服务器返回正确的index.html 却改变了.js 文件的内容?什么是实现我想要的正确方法,即防止访问我的 Angular 应用程序的所有部分,但登录页面除外?它在客户端很容易完成,但我也希望有一个服务器端保护,因为客户端很容易绕过。

这是服务器代码。实际上还有比这更多的事情(例如提供令牌的 API),但这并不重要。

const express = require("express");
const app = express();
const ejwt = require('express-jwt');

const static = express.static(__dirname + '/dist');

app.use('/dist', ejwt( secret: 'not so secret' ).unless( path: ['/dist/auth'] ), static);

// if 404 error, send index.html and let angular handle it
app.use('/app', function (req, res, next) 
  res.sendFile(__dirname + '/dist/index.html');
);

app.use('/app', function (err, req, res, next) 
  if (err.name === 'UnauthorizedError') 
     res.send('invalid token...');
  
);

app.use('/', function (req, res, next) 
  res.redirect('/app/');
);

app.listen(3000, () => console.log('Server is running'));

感谢您的帮助。

【问题讨论】:

【参考方案1】:

您已经快到了,您对 JWT 的概念以及使用中间件阻止对特定经过身份验证的页面的访问的想法似乎是正确的。您遇到的问题似乎与提供 Angular 应用程序有关。

要提供 Angular 应用程序,您可能不想使用 res.sendFile。相反,您可能希望在服务器代码的文件夹中拥有 Angular 应用程序的构建版本(来自ng build 的 dist 文件夹)。然后你要使用 Express 的静态函数。这是为提供静态内容而构建的,在这种情况下是您的前端代码。

您可能想要执行以下操作:

// Assume the frontend project is in the currentDir/frontend and the build is then in /dist.
app.use('/app', express.static(path.join(__dirname, '/frontend/dist')));

这将让 Express 管理通过转到 localhost:3000/app(假设您在端口 3000 上)为您的所有前端提供服务。

然后,您的所有其他端点都将是 JSON API 端点,这意味着它们将返回某种 HTTP 状态代码,并返回 JSON 作为响应。然后,您的 Angular 应用程序可以处理用户在前端执行的所有操作,并且只需调用 API。

如果有人尝试访问localhost:3000/app/secret-page,Angular 将向您的 API 发出 HTTP GET 调用,请求获取机密信息。如果没有提供 JWT,那么服务器会说“nope”并返回类似

HTTP Status Code: 404
Body:  message: "Nothing to see here" 

这样一来,只要用户访问 localhost:3000/app,您的前端就会得到服务,然后其余的调用都由您的快速代码处理,只处理 JSON 响应(没有 HTML 文件)。

这是一个非常基本的示例,您可能希望对此进行改进,例如在 / 路由而不是 /app 上提供 angular 应用程序,但这些似乎超出了这个问题的范围有很多资源可以帮助解决这个问题。

【讨论】:

以上是关于尝试使用 express-jwt 阻止访问除登录页面以外的 Angular 应用程序时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

不安全登录被阻止:您无法获取访问令牌或从不安全页面登录到此应用程序。尝试将页面重新加载为 https://

Express-jwt 中间件打字稿类型问题

express-jwt 的任何完整示例? [关闭]

使用 express-jwt 进行基于角色的授权?

S3 拒绝管理员访问

ReCaptcha 正在阻止我在 Localhost 中的 Wordpress 登录访问