如何在运行时导入 Vue 组件的 webpack 块时添加授权头 [英] How to add authorization header when runtime import webpack chunks of Vue components

查看:38
本文介绍了如何在运行时导入 Vue 组件的 webpack 块时添加授权头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此任务的目的是让知道组件地址但没有访问令牌的情况下无法下载 Vue-component 包(*.js 文件).

The purpose of this task is to make it impossible to download the Vue-component package (*.js file) knowing the address of the component, but not having an access token.

我正在开发一个访问控制系统和一个用户界面,其中可用组件集取决于用户的访问级别.

I'm developing an access control system and a user interface in which the set of available components depends on the user's access level.

系统使用JSON API和JWT授权.为此,在客户端使用 Axios.为了构建应用程序,我们使用 Webpack 4,加载组件,我们使用 vue-loader.

The system uses the JSON API and JWT authorization. For this, Axios is used on the client side. To build the application, we use Webpack 4, to load the components, we use the vue-loader.

在用户获得授权后,应用程序从服务器请求一组可用的路由和元数据,然后动态构造的菜单和路由被添加到 VueRouter 对象中.

After the user is authorized, the application requests an array of available routes and metadata from the server, then a dynamically constructed menu and routes are added to the VueRouter object.

下面我给出了一个简化的代码.

Below I gave a simplified code.

            import axios from 'axios'
            import router from 'router'

            let API = axios.create({
              baseURL: '/api/v1/',
              headers: {
                Authorization: 'Bearer mySecretToken12345'
              }
            })

            let buildRoutesRecursive = jsonRoutes => {
              let routes = []
              jsonRoutes.forEach(r => {
                let path = r.path.slice(1)
                let route = {
                  path: r.path,
                  component: () => import(/* webpackChunkName: "restricted/[request]" */ 'views/restricted/' + path)
                  //example path: 'dashboard/users.vue', 'dashboard/reports.vue', etc...
                }
                if (r.children)
                  route.children = buildRoutesRecursive(r.children)
                routes.push(route)
              })
              return routes
            }

            API.get('user/routes').then(
              response => {

                /*
                  response.data = 
                        [{
                      "path": "/dashboard",
                      "icon": "fas fa-sliders-h",
                              "children": [{
                        "path": "/dashboard/users",
                        "icon": "fa fa-users",
                                }, {
                        "path": "/dashboard/reports",
                        "icon": "fa fa-indent"
                                }
                            ]
                        }
                    ]
                */

                let vueRoutes = buildRoutesRecursive(response.data)
                router.addRoutes(vueRoutes)   
              },
              error => console.log(error)
            )

我遇到的问题是因为 Webpack 通过添加 'script' 元素而不是通过 AJAX 请求加载组件.因此,我不知道如何向此下载添加授权标头.因此,任何没有令牌的用户只需将其地址插入浏览器的导航栏中即可下载私有组件的代码.

The problem I'm having is because Webpack loads the components, by adding the 'script' element, and not through the AJAX request. Therefore, I do not know how to add an authorization header to this download. As a result, any user who does not have a token can download the code of the private component by simply inserting his address into the navigation bar of the browser.

理想情况下,我想知道如何使用 Axios 导入 vue 组件.

Ideally, I would like to know how to import a vue component using Axios.

或者,如何向 HTTP 请求添加授权标头.

Or, how to add an authorization header to an HTTP request.

推荐答案

虽然 sspiff 的回答看起来很有希望,它对我没有直接作用.

Although sspiff's answer looks quite promising, it did not work directly for me.

经过一些调查,这主要是由于我使用了 Vue CLI 3,因此使用了较新版本的 webpack.(这有点奇怪,因为 sspiff 提到使用 webpack 4.16.1).

After some investigation this was mainly due to me using Vue CLI 3 and thus a newer version of webpack. (which is kinda weird as sspiff mentioned using webpack 4.16.1).

无论如何解决它我使用了以下来源:medium.com,这给了我编辑给定代码的知识.

Anyway to solve it I used the following source: medium.com, Which gave me the knowledge to edit the given code.

这个新代码位于 vue.config.js 文件中:

This new code is situated in vue.config.js file:

/*
 * This plugin will call dynamicImportScriptHook() just before
 * the script element is added to the DOM. The script object is
 * passed to dynamicImportScriptHook(), and it should return
 * the script object or a replacement.
 */
class DynamicImportScriptHookPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap(
      "DynamicImportScriptHookPlugin", (compilation) =>
        compilation.mainTemplate.hooks.render.tap(
          {
            name: "DynamicImportScriptHookPlugin",
            stage: Infinity
          },
          rawSource => {
          const sourceString = rawSource.source()

          if (!sourceString.includes('jsonpScriptSrc')) {
            return sourceString;
          } else {
            const sourceArray = sourceString.split('script.src = jsonpScriptSrc(chunkId);')

            const newArray = [
              sourceArray[0],
              'script.src = jsonpScriptSrc(chunkId);',
              "\n\nif (typeof dynamicImportScriptHook === 'function') {\n",
              "  script = dynamicImportScriptHook(script);\n",
              "}\n",
              sourceArray[1]
            ]

            return newArray.join("")
          }
        }
      )
    );
  }
}

module.exports = {
  chainWebpack: (config) => {
    config.plugins.delete('prefetch')
  },
  configureWebpack: {
    plugins: [
      new DynamicImportScriptHookPlugin()
    ]
  }
}

sspiff提供的第二段代码保持不变,可以放在App.vue文件中或者脚本标签之间的 index.html.

The second piece of code provided by sspiff has stayed the same and can be placed in the App.vue file or the index.html between script tags.

为了进一步改进这个答案,我现在将解释如何在 Vue CLI 3 中为此特定目的拆分块.

Also to further improve this answer I will now explain how to split the chunks in Vue CLI 3 for this specific purpose.

如您所见,我还在配置中添加了 chainWebpack 字段.这确保 webpack 不会在 index.html 中添加 prefetch 标签.(例如,它现在只会在需要时加载惰性块)

as you can see I also added the chainWebpack field to the config. This makes sure that webpack does not add prefetch tags in the index.html. (e.g. it will now only load lazy chunks when they are needed)

为了进一步改善您的拆分,我建议您将所有导入更改为:

To further improve your splitting I suggest changing all your imports to something like:

component: () => import(/* webpackChunkName: "public/componentName" */ /* webpackPrefetch: true */'@/components/yourpubliccomponent')

component: () => import(/* webpackChunkName: "private/componentName" */ /* webpackPrefetch: false */'@/components/yourprivatecomponent')

这将确保您的所有私有块最终都位于私有文件夹中,并且不会被预取.公共块将最终位于公共文件夹中并被预取.

This will make sure that all your private chunks end up in a private folder and that they will not get prefetched. The public chunks will end up in a public folder and will get prefetched.

有关更多信息,请使用以下来源 how-to-make-lazy-loading-actually-work-in-vue-cli-3

For more information use the following source how-to-make-lazy-loading-actually-work-in-vue-cli-3

希望这可以帮助任何有此问题的人!

Hope this helps anyone with this problem!

这篇关于如何在运行时导入 Vue 组件的 webpack 块时添加授权头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆