简体   繁体   English

即使使用 ASP.NET CORE 登录,我在 Angular 中也有 401 Unauthorized

[英]I have a 401 Unauthorized in Angular even when login whit ASP.NET CORE

I have create a login in Angular.我已经在 Angular 中创建了一个登录名。 I am able to login when I am logged in I get a jwt key.我可以在登录时登录我得到一个 jwt 密钥。 My issuse is when I am loged in I should be able to get a lists of clients from my api.我的问题是当我登录时,我应该能够从我的 api 中获取客户列表。 I am following the instuctions here https://code-maze.com/authentication-aspnetcore-jwt-2/ I dont understand why I get a 401 when I try to get the clients from my api.我正在遵循此处的说明https://code-maze.com/authentication-aspnetcore-jwt-2/我不明白为什么当我尝试从我的 api 获取客户端时会收到 401。

Here are the releated angular files这是相关的角度文件

I have auth-guard.service.ts我有 auth-guard.service.ts

    import { Injectable } from '@angular/core';
    import { CanActivate, Router } from '@angular/router';
    import { JwtHelperService } from '@auth0/angular-jwt';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuard implements CanActivate {
    
      constructor(private router: Router, private jwtHelper: JwtHelperService) {}
    
    
      canActivate() {
        const token = localStorage.getItem("jwt");
    
        if (token && !this.jwtHelper.isTokenExpired(token)) {
          return true;
        }
        this.router.navigate(["login"]);
        return false;
      }
 }

The login component works登录组件工作

@Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent { invalidLogin: boolean; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) 导出类 LoginComponent { invalidLogin: boolean;

  constructor(private router: Router, private http: HttpClient) { }

  login(form: NgForm) {
    const credentials = JSON.stringify(form.value);
    this.http.post("https://localhost:44363/api/auth/login", credentials, {
      headers: new HttpHeaders({
        "Content-Type": "application/json"
      })
    }).subscribe(response => {
      const token = (<any>response).token;
      localStorage.setItem("jwt", token);
      this.invalidLogin = false;
      this.router.navigate(["/"]);
    }, err => {
      this.invalidLogin = true;
    });
  } 
}

Here is my app.module这是我的 app.module

export function tokenGetter() {
  return localStorage.getItem("jwt");
}


@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent,
    LocationManagerComponent,
    ClientsComponent,
    ClientDetailsComponent,
    LoginComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    DataTablesModule,
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full' },
      { path: 'counter', component: CounterComponent },
      { path: 'fetch-data', component: FetchDataComponent },
      { path: 'location-manager', component: LocationManagerComponent },
      { path: 'clients', component: ClientsComponent, canActivate: [AuthGuard]  },
      { path: 'clients/:clientId', component: ClientDetailsComponent, canActivate: [AuthGuard] },
      { path: 'login', component: LoginComponent },
    ]),
    BrowserAnimationsModule,
    JwtModule.forRoot({
      config: {
        tokenGetter: tokenGetter,
        whitelistedDomains: ["localhost:44363"],
        blacklistedRoutes: []
      }
    })
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})
export class AppModule {}

Finnaly here is the file that is causing my problems.最后这里是导致我的问题的文件。 When I try and get the clients from my api I get a 401 in my browser.当我尝试从我的 api 获取客户端时,我的浏览器中出现 401。

@Component({
  selector: 'app-clients',
  templateUrl: './clients.component.html',
  styleUrls: ['./clients.component.css']
})
export class ClientsComponent implements OnInit {
  dtOptions: DataTables.Settings = {};
  public clients: Client[];

  constructor(private http: HttpClient) { }


  ngOnInit(): void {
    this.dtOptions = {
      pagingType: 'full_numbers',
      pageLength: 10,
      processing: true
    };
    this.http.get<Client[]>('https://localhost:44363/api/clients', {
      headers: new HttpHeaders({
        "Content-Type": "application/json"
      })
    }).subscribe(result => {
      this.clients = result;
    }, error => {
      console.log(error)
    });
  }

  onSubmit(closet: any, drawer: any) {
    //get the value by its property
    console.log("Closet: " + closet);
    console.log("Drawer: " + drawer);
  }
}

Here are the releated csharp files这是相关的 csharp 文件

In my startup I configured it so that angular is used and that the jwt key is ussed.在我的启动中,我对其进行了配置,以便使用 angular 并使用 jwt 键。

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("EnableCORS", builder => 
            {
                builder.AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod();
            });
        });

        services.AddAuthentication(opt =>
        {
            opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(opttions =>
        {

            opttions.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,

                ValidIssuer = "https://localhost:44363",
                ValidAudience = "https://localhost:44363",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@45"))
            };
        });

        services.AddControllersWithViews();
       
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
        
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddTransient<DatabaseMigrator>();
        services.AddDbContext<erp_colombiaDbContext>(options => options.UseMySql(
                 Configuration.GetConnectionString("DefaultConnection"),
                 optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(DesignTimeDbContextFactory).Assembly.FullName)));

        services.AddDbContext<erp_colombiaDbContext>(options => options.UseMySql(
                Configuration.GetConnectionString("DefaultConnection"),
                optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(DesignTimeDbContextFactory).Assembly.FullName)));
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseCors("EnableCORS");

        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }

Here is controller where I want to get the list of clients from这是我想从中获取客户列表的控制器

// GET api/clients
[HttpGet]
[Authorize]
public IEnumerable<ClientViewModel> Get()
{
    ClientViewModel clientViewModel;
    List<ClientViewModel> listClientViewModels = new List<ClientViewModel>();

    var clients = Task.Run(async () => await _clientService.GetAllClients()).Result;

    foreach (var client in clients) 
    {
        clientViewModel = new ClientViewModel();
        clientViewModel.ClientId = client.ClientId;
        clientViewModel.Active = client.Active;
        clientViewModel.Address = client.Address;
        clientViewModel.City = client.City;
        clientViewModel.ClienteName = client.ClienteName;
        clientViewModel.ComercialEmployeeId = client.ComercialEmployeeId;
        clientViewModel.Confirmed = client.Confirmed;
        clientViewModel.CountryId = client.CountryId;
        clientViewModel.CreationDate = client.CreationDate;
        clientViewModel.DANE = client.DANE;
        clientViewModel.Department = client.Department;
        clientViewModel.ElectronicBillingEmail = client.ElectronicBillingEmail;
        clientViewModel.Eliminated = client.Eliminated;
        clientViewModel.NIT = client.NIT;
        clientViewModel.PostalCode = client.PostalCode;
        clientViewModel.Phone = client.Phone;

        listClientViewModels.Add(clientViewModel);
    }

    return listClientViewModels;
}

If I'm not mistaken you are getting 401, cuz your request isn't Authorized .如果我没记错的话,您收到的是 401,因为您的请求未Authorized

So you can just add Authorization header to your request like:因此,您可以将Authorization标头添加到您的请求中,例如:

headers: new HttpHeaders({
    "Authorization": `Bearer ${localStorage.getItem("jwt")}`,
    "Content-Type": "application/json"
})

But I strongly recommend using Interceptor that will apply Authorization token for every request (one time defined, no need to duplicate the code\\headers, etc)但我强烈建议使用Interceptor为每个请求应用Authorization token (一次定义,无需复制代码\\标头等)

@Injectable()
export class ApplyJWTTokenInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const idToken = localStorage.getItem("jwt");

        if (idToken) {
            const authClonedRequest = req.clone({
                headers: req.headers
                    .set('Authorization', `Bearer ${idToken}`)
            });
            return next.handle(authClonedRequest);
        }
        else {
            return next.handle(req);
        }
    }
}

Recommended to check:建议检查:

  1. HTTPInterceptor HTTP拦截器
  2. Intercepting requests and responses 拦截请求和响应
  3. Worked demo 工作演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM