【问题标题】:How to hide server-side rendered HTML code in client-side如何在客户端隐藏服务器端呈现的 HTML 代码
【发布时间】:2019-04-17 19:51:58
【问题描述】:

我正在使用 Angular 7 开始一个项目,我想知道根据权限向用户隐藏“受保护”HTML 元素的最佳方法是什么。我知道最简单的方法是使用像 CASL 这样的库来处理它们,但我想要真正的权限/角色访问检查。

如果用户不应该看到一个按钮,它就不能被渲染,我知道 ngIf 和 ngShow,即使它不会到达 HTML,它也会出现在缩小的 bundle.js 中。

我的方法是使用 Angular Universal 并使用 isPlatformBrowser 和 isPlatformServer 进行一些测试,但我发现即使我使用类似以下的内容,当 Angular 在客户端引导时,代码仍然会出现在包中:

<ng-container *ngIf="isPlatformServerFunction() && hasAccess()"> <button> Secret Button </button> <ng-container>

¿有没有办法只在服务器端渲染某些东西,并且在服务器端渲染之后引导 HTML/JS 时不要让 HTML/JS 滑入前端?

我想知道这在 Facebook 等大型应用程序中是如何处理的,因为每个人都说它应该在前端,因为后端 API 是安全的,所以如果他们到达 UI,他们就赢了'无论如何都无法获取 API 的数据,但我在 Facebook 的公共包中看不到管理按钮/代码。

【问题讨论】:

  • 为什么不评估代码服务器端,甚至不让它到达客户端?
  • 在像 facebook 这样的网站中,每个人都有一个令牌,其中包含他们所有的访问权限(并存储在后端),没有它你不能做任何事情,包括管理员请求,所以在你的情况下假设你正在做一些带有凭据的请求(为什么不),那么您将创建一个后端接口,该接口或多或少地通过了请求,但添加了凭据,只有在您授权通过令牌调用该接口时才能调用。
  • 关于令牌系统的更多信息(最好使用 3rd 方系统)基本上你有一个登录请求到后端,它生成一个随机令牌或编码的详细信息,没有任何安全凭据并保存用户信息在数据库中使用该令牌(最好带有时间戳)然后将该令牌提供给前端,当用户尝试访问该界面时,您检查他是否向您传递了一个令牌并检查它是否存在于数据库中并连接到用户具有必要的权利(如果它在一个时间范围内),然后发送请求
  • 永远记住你在前端代码中“隐藏”的任何东西都可以通过开发者控制台中的简单控制台输入和网络日志功能的一点帮助来重现
  • 感谢您的见解和分享您在安全和 Facebook 方面的知识。这个想法实际上是不让代码到达客户端,而是让服务器渲染它并且不要让它滑到 JS 包中,如果可能的话,这在 PHP 中很容易,因为你决定渲染与否基于简单的条件,但在 SPA 中并不那么容易,因为有一个捆绑包正在创建和发送。在 SPA + SSR 方面,如果您想要相同的效果,那么也许我应该删除 bundle 中的 JS Angular 函数,但这应该在运行时完成,根据用户角色,这就是这里的复杂性

标签: javascript html angular angular-universal server-side-rendering


【解决方案1】:

有没有办法只在服务器端渲染一些东西,并且在服务器端渲染之后引导 HTML/JS 时不要让 HTML/JS 滑入前端

是的。

您必须为您的 Angular 项目构建两个不同的版本。一个包含 private 内容,另一个是 public。这可以通过为您的 Angular 项目定义多个环境来完成。

https://blog.angularindepth.com/becoming-an-angular-environmentalist-45a48f7c20d8

您可以在前端构建中定义假代理服务,但使用服务器端提供程序仅声明仅存在于服务器上的服务。这可以防止源代码进入捆绑包。

app.engine('html', ngExpressEngine({
  bootstrap: ServerAppModule,
  providers: [
    ServerService
  ]
}));

然后您需要创建一个server.ts,根据安全检查选择要引导的构建。如果您使用 cookie 或其他什么纯粹是不同的问题,您将如何执行此检查。

这是通过引导 Angular 服务器端渲染每个请求而不是 app.engine() 来完成的。

https://github.com/angular/universal/tree/master/modules/express-engine#advanced-usage

app.get('/**/*', (req: Request, res: Response) => {
  res.render('../dist/index', {
    req,
    res,
    bootstrap: OtherServerAppModule,
    providers: [
      OtherServerService
    ]
  });
});

正是在这段代码中,您将构建的逻辑添加到引导程序。

拼图的各个部分都可以实现您想要的安全性。我无法提供完整的教程来详细说明如何操作,但我希望我已经为您指明了正确的方向。

【讨论】:

  • 感谢您的宝贵时间。如果您有二进制私有或公共内容,我认为这是一个很好的方法,但是如果私有内容根据角色/权限发生变化怎么办? (我知道如何在服务器端进行身份验证/授权)它应该是动态的并在运行时完成,除非您为每个用户角色创建 10 个不同的捆绑包。目标是使用 ngIf 指令,例如检查组件的权限,如果他没有权限,则不要渲染 HTML,也不要将 JS 发送到包。使用 SSR 和 Angular 作为 SPA 是否可行?
猜你喜欢
  • 1970-01-01
  • 2022-09-28
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多