0

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

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

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

在客户端我正在使用:

  • ngx 管理员 3.2.1
  • 角度 7.2.1
  • 星云/认证 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; } },
    ],
})
4

2 回答 2

0

我最终挖掘了所有@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);
  }

}
于 2019-07-11T15:47:11.767 回答
0

我正在使用 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;
}
于 2019-10-02T19:20:45.557 回答