Angular扩展Nebular Auth实现邮箱验证时依赖注入报错求助
问题描述
我正在使用Nebular认证组件构建Angular应用,需要为注册功能添加自定义实现,并加入邮箱验证流程:用户注册时以inactive状态存入数据库,系统发送含验证链接的邮件,用户验证后账号标记为active。但陷入依赖注入问题,无法定位错误,相关代码及报错信息如下:
app.module.ts
@NgModule({ imports: [ BrowserModule, BrowserAnimationsModule, HttpClientModule, AppRoutingModule, SharedModule, ThemeModule.forRoot(), NbToastrModule.forRoot(), StoreModule.forRoot(reducers, { metaReducers, runtimeChecks: { strictStateImmutability: true, strictActionImmutability: true, }, }), EffectsModule.forRoot(), NbAuthModule.forRoot({ strategies: [ CustomAuthStrategy.setup({ name: "email", baseEndpoint: "/auth/", login: { endpoint: "login", redirect: { success: HOME_PAGE, failure: null, }, }, register: { endpoint: "register", redirect: { success: null, failure: null, }, }, verifyemail: { endpoint: "verify", }, logout: { endpoint: "", }, requestPass: { endpoint: "requestpass", }, resetPass: { endpoint: "resetpass", }, token: { class: NbAuthJWTToken, key: "token", }, }), ], forms: {}, }), ], declarations: [AppComponent], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AddTokenHeaderHttpRequestInterceptor, multi: true, }, ApiService, CustomAuthStrategy, { provide: NbAuthService, useClass: CustomAuthService }, NbTokenService, HttpClient, ], bootstrap: [AppComponent], }) export class AppModule {}
custom-auth.service.ts
@Injectable({ providedIn: "root", }) export class CustomAuthService extends NbAuthService { strategies: NbAuthStrategy[]; constructor( protected tokenService: NbTokenService, private injector: Injector, ) { // Initialize strategies after injector is available super(tokenService, []); this.strategies = this.injector.get(NbAuthStrategy, []); } verifyEmail( email: string, code: string, http: HttpClient, ): Observable<NbAuthResult> { const endpoint = "/auth/verify"; return http.post(endpoint, { email, code }).pipe( map((res: any) => { return new NbAuthResult( res.success, res, res.success ? "/auth/login" : null, res.success ? [] : ["Verification failed."], res.success ? ["Email verified successfully. Please log in."] : [], ); }), ); } }
custom-auth.strategy.ts
export interface CustomAuthStrategyOptions extends NbPasswordAuthStrategyOptions { verifyemail?: { endpoint: string; }; } @Injectable({ providedIn: "root", }) export class CustomAuthStrategy extends NbPasswordAuthStrategy { constructor( protected http: HttpClient, protected injector: Injector, route: ActivatedRoute, options: CustomAuthStrategyOptions, ) { super(http, route); } static setup( options: CustomAuthStrategyOptions, ): [typeof CustomAuthStrategy, CustomAuthStrategyOptions] { return [CustomAuthStrategy, options]; } protected handleResponse(res: any): NbAuthResult { if (res.success) { return new NbAuthResult( true, res, this.getOption("register.redirect.success"), [], res.message, ); } else { return new NbAuthResult( false, res, this.getOption("register.redirect.failure"), this.getOption("errors.getter")(res), this.getOption("messages.getter")(res), ); } } register(data?: any): Observable<NbAuthResult> { return this.http.post(this.getActionEndpoint("register"), data).pipe( map((res) => this.handleResponse(res)), catchError((res: HttpErrorResponse) => { return of( new NbAuthResult( false, res, this.getOption("register.redirect.failure"), this.getOption("errors.getter")(res), ), ); }), ); } }
报错信息
出现两个交替报错:
- Error: This constructor was not compatible with Dependency Injection.
at Module.ɵɵinvalidFactory (core.mjs:10057:11) at Object.CustomAuthStrategy_Factory [as factory] ( - NullInjectorError: NullInjectorError: No provider for NB_AUTH_STRATEGIES!
解决方案
1. 修复CustomAuthStrategy构造函数兼容性
Nebular的NbPasswordAuthStrategy构造函数参数需严格匹配父类定义,当前构造函数多余的Injector和options参数导致DI无法创建实例。修改custom-auth.strategy.ts:
@Injectable({ providedIn: "root", }) export class CustomAuthStrategy extends NbPasswordAuthStrategy { constructor( protected http: HttpClient, protected route: ActivatedRoute ) { super(http, route); } // 其余代码保持不变 }
2. 修复CustomAuthService的策略注入
NbAuthService依赖NB_AUTH_STRATEGIES令牌,手动通过Injector获取策略的方式错误,改为直接注入该令牌。同时优化verifyEmail方法,将HttpClient注入构造函数而非作为参数传入:
import { NB_AUTH_STRATEGIES } from '@nebular/auth'; // ...其他导入 @Injectable({ providedIn: "root", }) export class CustomAuthService extends NbAuthService { constructor( protected tokenService: NbTokenService, @Inject(NB_AUTH_STRATEGIES) protected strategies: NbAuthStrategy[], protected http: HttpClient ) { super(tokenService, strategies); } verifyEmail( email: string, code: string, ): Observable<NbAuthResult> { const endpoint = "/auth/verify"; return this.http.post(endpoint, { email, code }).pipe( map((res: any) => { return new NbAuthResult( res.success, res, res.success ? "/auth/login" : null, res.success ? [] : ["Verification failed."], res.success ? ["Email verified successfully. Please log in."] : [], ); }), ); } }
3. 清理AppModule的冗余配置
- 移除
providers中的CustomAuthStrategy,NbAuthModule.forRoot已通过strategies配置该策略,手动注册会导致冲突。 - 移除
HttpClient的手动注册,HttpClientModule已自动提供该服务。
修改后的app.module.ts providers部分:
providers: [ { provide: HTTP_INTERCEPTORS, useClass: AddTokenHeaderHttpRequestInterceptor, multi: true, }, ApiService, { provide: NbAuthService, useClass: CustomAuthService }, NbTokenService, ],
4. 确认策略配置加载
CustomAuthStrategy的setup方法返回的配置会被NbAuthModule自动处理,创建策略实例并注入到NB_AUTH_STRATEGIES中,无需手动注册。
内容的提问来源于stack exchange,提问作者user176504
相关产品推荐
相关产品推荐

