使用Angular 2 / ASP.NET Core 2.1应用程序。登录后,我可以从前端console.log JWT令牌,但是当我尝试使用[Authorize]
属性访问控制器(AccountsController.cs)时,出现401错误。如果删除该属性,并尝试使用var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
获取当前用户,我会立即被发送回前端并通过解析器收到错误消息。
似乎当前的用户数据没有与请求一起发送到后端。还是没有存储?还是我无法正确访问它?
account-list.resolver.ts
import { Resolve, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Account } from '../../_models/account';
import { Injectable } from '@angular/core';
import { AccountService } from '../../_services/account.service';
import { AlertifyService } from '../../_services/alertify.service';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
@Injectable()
export class AccountListResolver implements Resolve<Account[]> {
pageSize = 5;
pageNumber = 1;
constructor(private accountService: AccountService,
private router: Router,
private alertify: AlertifyService) {
}
resolve(route: ActivatedRouteSnapshot): Observable<Account[]> {
return this.accountService.getAccounts(this.pageNumber, this.pageSize).catch(error => {
this.alertify.error('Problem retrieving data');
this.router.navigate(['/dashboard']);
return Observable.of(null);
});
}
}
account.service.ts
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { Account } from '../_models/account';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { PaginatedResult } from '../_models/pagination';
import { HttpClient, HttpParams } from '@angular/common/http';
@Injectable()
export class AccountService {
baseUrl = environment.apiUrl;
constructor(private authHttp: HttpClient) { }
getAccounts(page?, itemsPerPage?, accountParams?: any) {
const paginatedResult: PaginatedResult<Account[]> = new PaginatedResult<Account[]>();
let params = new HttpParams();
if (page != null && itemsPerPage != null) {
params = params.append('pageNumber', page);
params = params.append('pageSize', itemsPerPage);
}
// if (accountParams != null) {
// params = params.append('paramName', accountParams.paramName);
// }
return this.authHttp
.get<Account[]>(this.baseUrl + 'accounts', { observe: 'response', params })
.map(response => {
paginatedResult.result = response.body;
if (response.headers.get('Pagination') != null) {
paginatedResult.pagination = JSON.parse(response.headers.get('Pagination'));
}
return paginatedResult;
});
}
}
AccountsController
[Authorize]
[Route("api/[controller]")]
public class AccountsController : Controller
{
private readonly IBaseRepository _repo;
private readonly IMapper _mapper;
public AccountsController(IBaseRepository repo, IMapper mapper)
{
_mapper = mapper;
_repo = repo;
}
[HttpGet]
public async Task<IActionResult> GetAccounts([FromQuery] AccountParams accountParams)
{
var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
//^^^WHERE IT BREAKS WHEN AUTHORIZATION ATTRIBUTE IS REMOVED
//code to generate list of accounts to return
accountParams.UserId = currentUserId;
var accounts = await _repo.GetAccounts(accountParams);
var accountsToReturn = _mapper.Map<IEnumerable<AccountForListDto>>(accounts);
Response.AddPagination(accounts.CurrentPage, accounts.PageSize, accounts.TotalCount, accounts.TotalPages);
return Ok(accountsToReturn);
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
services.AddDbContext<DataContext>(x => x
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b =>
b.MigrationsAssembly(("MyApp.App")))
.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));
services.AddMvc()
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });
services.AddTransient<Seed>();
services.AddCors();
services.AddAutoMapper();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddScoped<IBaseRepository, BaseRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddScoped<LogUserActivity>();
}
public void ConfigureDevelopmentServices(IServiceCollection services)
{
var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
services.AddDbContext<DataContext>(x => x
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b =>
b.MigrationsAssembly(("MyApp.App")))
.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));
services.AddMvc()
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });
services.AddTransient<Seed>();
services.AddCors();
services.AddAutoMapper();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddScoped<IBaseRepository, BaseRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddScoped<LogUserActivity>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message);
}
});
});
}
app.ConfigureSwagger(Assembly.GetExecutingAssembly());
app.UseCors(x => x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
app.UseDefaultFiles();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
//spa.UseAngularCliServer(npmScript: "start");
}
});
}
答案 0 :(得分:2)
您添加了JWT授权处理程序吗?
在您的startup.cs
app.UseAuthentication()
方法中是否有Configure
? app.UseMvc()
之前吗? app.AddAuthentication()
方法中是否有ConfigureServices
? app.AddMvc()
之前吗? AddJwtBearer()
方法挂起中是否有对ConfigureServices
的调用
不打AddAuthentication()
? Authorize
属性中为承载指定了方案名称? 在您的配置中,好像您在configure方法中缺少app.UseAuthentication()。
因此您需要像这样将其放在app.UseMvc()之前;
app.UseSpaStaticFiles();
app.UseAuthentication()
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});