[英]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。
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);
}
}
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:
建议检查:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.