带有 vuex-oidc 的 Vue.js SPA 在发布版本上有重定向循环

Posted

技术标签:

【中文标题】带有 vuex-oidc 的 Vue.js SPA 在发布版本上有重定向循环【英文标题】:Vue.js SPA with vuex-oidc has redirect loops on release version 【发布时间】:2019-07-20 00:17:10 【问题描述】:

我有一个在 Vue.js 2.5 中构建的单页应用程序,它还使用 IdentityServer4 + vuex-oidc 支持 OAuth2.0,并在 nginx 服务器上运行。在 webpack dev server 上运行应用程序时,我的设置 一切正常,但发布版本存在重定向循环问题,我高度怀疑这可能是由于 nginx 配置错误。

问题:重定向循环行为始终相同

    用户请求导航到 /app oidc 插件重定向到 /connect/authorize?... 重定向到 /app/oidc-login(授权请求的重定向 uri) 重定向到 /app(返回第 2 步)

对于开发服务器,我使用配置为的反向代理

location /app 
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass https://127.0.0.1:55100;
    proxy_temp_path C:/myapp/nginxRP;

但是由于我在路由器中使用历史模式,所以发布版本是按照https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations配置的

fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
location /app 
    try_files $uri $uri/ /index.html;

应用程序的发布版本(index.html 和静态文件)位于 ..\nginx\html\app

这是我的 vue-router 配置

const router = new Router(
    mode: "history",
    base: "/app/",
    routes: [
        
            path: "/oidc-login",
            name: "oidcCallback",
            component: OidcCallback,
            meta: 
                isOidcCallback: true,
                isPublic: true
            
        ,
        
            path: "/oidc-silent-login",
            name: "oidcSilentCallback",
            component: OidcSilentCallback,
            meta: 
                isOidcCallback: false,
                isPublic: true
            
        ,
        
            path: "/",
            name: HOME_PAGE_TITLE,
            component: Main
        ,
        
            path: "*",
            name: "Page Not Found",
            component: NotFound
        
    ]
);

而 OidcCallback 组件是

<template>
  <div></div>
</template>

<script>
import  mapActions  from "vuex";
import  OIDC_MODULE_NAMESPACE  from "../../store/store";

export default 
    name: "OidcCallback",
    methods: 
        ...mapActions(OIDC_MODULE_NAMESPACE, [
            "oidcSignInCallback"
        ])
    ,
    mounted () 
        this.oidcSignInCallback()
            .then((redirectPath) => 
                this.$router.push(redirectPath);
            )
            .catch((err) => 
                console.error(err);
                this.$router.push("/signin-oidc-error"); // TODO
            );
    
;
</script>

除了我将 oidcStore 模块动态添加到 vuex 之外,我几乎完全按照 https://github.com/perarnborg/vuex-oidc/wiki#how-to-implement-vuex-oidc 中的说明配置了 vuex-oidc。

由于一切都在开发服务器中正常工作,而且我已经认为这是一个 nginx 问题,我不确定提供我的代码/设置的其他部分是否会有所帮助,但如果我遗漏了什么,请告诉我我会分享更多。

谢谢

【问题讨论】:

【参考方案1】:

正如我之前所怀疑的,问题实际上是 nginx 部分的错误配置。基本上,网络服务器正在剥离从 IdentityServer(和任何其他查询参数)返回的 id_token 参数,这导致了重定向循环。有两种解决方案。简单的解决方案是在 nginx 配置中添加一个重写规则,然后将其替换为类似

location ^~ /app/ 
    if (!-f $request_filename) 
        rewrite ^/app/(.*)$ /app/index.html;
    

这样它就可以正确地将每个 url 查询传递给 Vue 应用程序,然后由 Vue-Router 和 vuex-oidc 中间件处理(设置 vue-router 时不需要更改,只需上述 nginx 配置就足够了)。 另一种解决方案是使用"Front Controller Pattern" 设计并将完整的uri 及其参数传递给SPA。这仍然需要像配置 nginx 有点不同

location /app 
    try_files $uri $uri/ /index.html?route=$uri&$args;

不再重写,但在 Vue-Router 中额外施加了特殊处理,以便使用导航守卫从那里执行导航,这个 route 查询类似于建议的 here。

【讨论】:

以上是关于带有 vuex-oidc 的 Vue.js SPA 在发布版本上有重定向循环的主要内容,如果未能解决你的问题,请参考以下文章

使用 httponly cookie 将 JWT 从节点 REST API 发送到 Vue.js SPA

Laravel + Vue.js MPA/SPA 混合结构的建议和思考

如何创建服务于 Vue.js SPA 的 Node.js Express 应用程序?

Vue.js:如何在已打开的选项卡中打开外部链接?

如何使用 Vue.js 制作 MPA? (或者这个项目应该是一个SPA?)

Vue.js写一个SPA登录页面的过程