【问题标题】:Problem with configuring NbAuthJWTInterceptor to format JWT tokens appropriately配置 NbAuthJWTInterceptor 以正确格式化 JWT 令牌的问题
【发布时间】:2019-11-20 02:39:54
【问题描述】:

我正在为我的新应用程序使用 ngx-admin。我已经利用 Nebular Auth 框架来使用 JWT 令牌来启用对后端 REST 服务器的访问。

在使用 Postman 测试 API 时,我可以通过使用 JWT <token> 格式的令牌格式化 Authorization HTTP 标头来成功验证和访问 REST 服务器。从基于 ngx-admin 的应用程序访问 API 的问题是 NbAuthJWTInterceptor 类以 Bearer JWT <token> 格式显示 Authorization HTTP 标头,因此我的后端 API 无法提取令牌。

如何配置或覆盖 NbAuthJWTInterceptor 类以将 Authorization HTTP 标头设置为 JWT <token> 格式?

在我使用的客户端:

  • ngx-admin 3.2.1
  • 角度7.2.1
  • nebular/auth 3.4.2

在服务器端,我将以下内容与 MongoDB 一起使用:

  • 快递4.6.13
  • 护照0.4.0
  • 护照-jwt 4.0.0
  • jsonwebtoken 8.5.1
  • 猫鼬 5.1.7

我已经使用我已使用 Postman 成功登录的令牌测试了对我的 API 的各种调用(GET、POST、PUT、DELETE),并将授权令牌格式化为JWT <token>,并且请求已获得授权,并且正确的数据是回来。

当我的应用程序提出相同的请求时,NbAuthJWTInterceptor 类将授权令牌格式化为 Bearer JWT <token>,因此请求被拒绝为“未经授权”

在 REST 服务器端访问和解码授权令牌:

module.exports = function (passport) {
    var opts = {};
    opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('JWT');
    opts.secretOrKey = config.secret;

    passport.use(new JwtStrategy(opts, function (jwt_payload, done) {
        User.findOne({
            id: jwt_payload._id        
        }, function (err, user) {
            if (err) {
                return done(err, false);
            }
            if (user) {
                done(null, user);
            } else {
                done(null, false);
            }
        });
    }));
};

配置 API 端点和 HTTP 拦截器以在客户端注入授权令牌:

@NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        HttpClientModule,
        AppRoutingModule,

        // NbEvaIconsModule,

        NgbModule.forRoot(),
        ThemeModule.forRoot(),
        CoreModule.forRoot(),

        NbAuthModule.forRoot({
            strategies: [
                NbPasswordAuthStrategy.setup({
                    name: 'email',
                    token: {
                        class: NbAuthJWTToken,
                        key: 'token',
                    },

                    baseEndpoint: '/api',
                    login: {
                        endpoint: '/auth/signin',
                        method: 'post',
                    },
                    register: {
                        endpoint: '/auth/signup',
                        method: 'post',
                    },
                    logout: {
                        endpoint: '/auth/sign-out',
                        method: 'post',
                    },
                    requestPass: {
                        endpoint: '/auth/request-pass',
                        method: 'post',
                    },
                    resetPass: {
                        endpoint: '/auth/reset-pass',
                        method: 'post',
                    },
                }),
            ],
            forms: {
                login: formDelaySetting,
                register: formDelaySetting,
                requestPassword: formSetting,
                resetPassword: formSetting,
                logout: {
                    redirectDelay: 0,
                },
            },
        }),

        NbThemeModule.forRoot({ name: 'corporate' }),

        NbToastrModule.forRoot(),

        NbLayoutModule,
    ],
    bootstrap: [AppComponent],
    providers: [
        { provide: APP_BASE_HREF, useValue: '/' }, 
        { provide: HTTP_INTERCEPTORS, useClass: NbAuthJWTInterceptor, multi: true },
        { provide: NB_AUTH_TOKEN_INTERCEPTOR_FILTER, useValue: (req) => { return false; } },
    ],
})

【问题讨论】:

    标签: node.js authentication jwt ngx-admin


    【解决方案1】:

    我最终挖掘了所有 @Nebular/auth 模块代码并最终找到了罪魁祸首。 NbAuthJWTInterceptor 具有硬编码的网络令牌的“承载”部分。所以我不得不克隆类并制作,然后使用我自己的 HTTP 拦截器:

    import { Inject, Injectable, Injector } from '@angular/core';
    import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { switchMap } from 'rxjs/operators';
    import { NbAuthToken } from '@nebular/auth';
    import { NbAuthService } from '@nebular/auth';
    import { NB_AUTH_TOKEN_INTERCEPTOR_FILTER } from '@nebular/auth';
    
    @Injectable()
    export class NgxAuthJWTInterceptor implements HttpInterceptor {
    
      constructor(private injector: Injector,
                  @Inject(NB_AUTH_TOKEN_INTERCEPTOR_FILTER) protected filter) {
      }
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // do not intercept request whose urls are filtered by the injected filter
          if (!this.filter(req)) {
            return this.authService.isAuthenticatedOrRefresh()
              .pipe(
                switchMap(authenticated => {
                  if (authenticated) {
                      return this.authService.getToken().pipe(
                        switchMap((token: NbAuthToken) => {
                          //const JWT = `Bearer ${token.getValue()}`;  <--- replace this line with the next
                          const JWT = `${token.getValue()}`;
                          req = req.clone({
                            setHeaders: {
                              Authorization: JWT,
                            },
                          });
                          return next.handle(req);
                        }),
                      )
                  } else {
                     // Request is sent to server without authentication so that the client code
                     // receives the 401/403 error and can act as desired ('session expired', redirect to login, aso)
                    return next.handle(req);
                  }
                }),
              )
          } else {
          return next.handle(req);
        }
      }
    
      protected get authService(): NbAuthService {
        return this.injector.get(NbAuthService);
      }
    
    }
    

    【讨论】:

      【解决方案2】:

      我正在使用 nebular/auth 4.2.1 并且仍然有同样的问题,检查代码出现一些文件夹:esm2015 和 esm5 有一些调用但不清楚,在服务中只有这个:

      export declare class NbAuthJWTInterceptor implements HttpInterceptor {
          private injector;
          protected filter: any;
          constructor(injector: Injector, filter: any);
          intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;
          protected readonly authService: NbAuthService;
      }
      

      【讨论】:

        猜你喜欢
        • 2020-03-01
        • 2018-11-12
        • 2021-11-16
        • 2018-03-02
        • 1970-01-01
        • 2019-07-28
        • 1970-01-01
        • 1970-01-01
        • 2019-09-27
        相关资源
        最近更新 更多