首先,package.json
:
"@angular/cli": "^6.0.8",
"rxjs": "6.2.1",
我正在跟踪带有角度教程的asp.net核心2。我不得不修改一些代码,因为它被认为是较旧的版本。
本章是关于创建JWT身份验证的。
我得到了承载令牌,但是当api controller
返回响应时,auth.service
得到了空响应,而let token = res && res.token;
的行if
变为false,因此它永远都不会得到确定。
我怀疑TokenResponse的演员表出了点问题,但我不知道是什么。
token.response.ts
interface TokenResponse {
token: string,
expiration: number
}
auth.service.ts
import { EventEmitter, Inject, Injectable, PLATFORM_ID } from "@angular/core";
import { isPlatformBrowser } from '@angular/common';
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Observable } from "rxjs";
import { map, catchError } from 'rxjs/operators';
import 'rxjs/Rx';
@Injectable()
export class AuthService {
authKey: string = "auth";
clientId: string = "NetCoreAngularWeb";
constructor(private http: HttpClient,
@Inject(PLATFORM_ID) private platformId: any) {
}
// performs the login
login(username: string, password: string): Observable<boolean> {
var url = "api/token/auth";
var data = {
username: username,
password: password,
client_id: this.clientId,
// required when signing up with username/password
grant_type: "password",
// space-separated list of scopes for which the token is
// issued
scope: "offline_access profile email"
};
return this.http.post<TokenResponse>(url, data)
.pipe(
map(res => {
let token = res && res.token;
// if the token is there, login has been successful
if (token) {
// store username and jwt token
this.setAuth(res);
// successful login
return true;
}
// failed login
return Observable.throw('Unauthorized');
}),
catchError(error => {
return new Observable<any>(error);
})
);
}
// performs the logout
logout(): boolean {
this.setAuth(null);
return true;
}
// Persist auth into localStorage or removes it if a NULL argument is given
setAuth(auth: TokenResponse | null): boolean {
if (isPlatformBrowser(this.platformId)) {
if (auth) {
localStorage.setItem(
this.authKey,
JSON.stringify(auth));
}
else {
localStorage.removeItem(this.authKey);
}
}
return true;
}
// Retrieves the auth JSON object (or NULL if none)
getAuth(): TokenResponse | null {
if (isPlatformBrowser(this.platformId)) {
var i = localStorage.getItem(this.authKey);
if (i) {
return JSON.parse(i);
}
}
return null;
}
// Returns TRUE if the user is logged in, FALSE otherwise.
isLoggedIn(): boolean {
if (isPlatformBrowser(this.platformId)) {
return localStorage.getItem(this.authKey) != null;
}
return false;
}
}
TokenController
[HttpPost("Auth")]
public async Task<IActionResult> Auth([FromBody]TokenRequestViewModel model)
{
// return a generic HTTP Status 500 (server Error)
// if the client payload is invalid.
if (model == null) return new StatusCodeResult(500);
switch (model.grant_type)
{
case "password":
return await GetToken(model);
default:
// not supported - return a HTTP 401 (Unauthorized)
return new UnauthorizedResult();
}
}
private async Task<IActionResult> GetToken(TokenRequestViewModel model)
{
try
{
// check if there's an user with the given username
var user = await UserManager.FindByNameAsync(model.username);
// fallback to support e-mail address instead of username
if (user == null && model.username.Contains("@"))
user = await UserManager.FindByEmailAsync(model.username);
if (user == null || !await UserManager.CheckPasswordAsync(user, model.password))
{
// user does not exists or password mismatch
return new UnauthorizedResult();
}
// username & password matches: create and return the Jwt token
DateTime now = DateTime.UtcNow;
// add the registered claims for JWT (RFC7519)
// For more info, see...
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(now).ToUnixTimeSeconds().ToString())
// TODO add additional claims here
};
var tokenExpirationMins = Configuration.GetValue<int>("Auth:Jwt:TokenExpirationInMinutes");
var issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"]));
var token = new JwtSecurityToken(
issuer: Configuration["Auth:Jwt:Issuer"],
audience: Configuration["Auth:Jwt:Audicnete"],
claims: claims,
notBefore: now,
expires:
now.Add(TimeSpan.FromMinutes(tokenExpirationMins)),
signingCredentials: new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256)
);
var encodedToken = new JwtSecurityTokenHandler().WriteToken(token);
// build & return the response
var response = new TokenResponseViewModel()
{
token = encodedToken,
expiration = tokenExpirationMins
};
return Json(response);
}
catch (Exception ex)
{
return new UnauthorizedResult();
}
}
编辑-响应,由POSTMAN检查
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlODBiNzRkMi0xOGIwLTQ5NzUtOWUyYS0wOGJiOGJlOTUzMDEiLCJqdGkiOiIzNTkzNjVhYS02M2UyLTQ3ZGMtYjY1NC1mMDk3YWQxNjNmMzQiLCJpYXQiOiIxNTMwNzEzMzU2IiwibmJmIjoxNTMwNzEzMzU2LCJleHAiOjE1MzU4OTczNTYsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzE3NzkvIn0.6QlGCK_4ybzYEz8qaRDDotOja6x0FI0fZTxmky94S5Y",
"expiration": 86400
}
Status 200 OK
Time:11281 ms
Size:671 B
Content-Type →application/json; charset=utf-8
Date →Wed, 04 Jul 2018 14:09:21 GMT
Server →Kestrel
Transfer-Encoding →chunked
X-Powered-By →ASP.NET
答案 0 :(得分:0)
嗯,这里有几个问题。 首先,我的Chrome版本破坏了VS Studio调试器。我必须将其更新到63+版本(以我的情况为65) https://social.msdn.microsoft.com/Forums/vstudio/en-US/5cd1aa58-d986-4d03-a10e-bf1fd62080a7/simultaneous-debugging-in-chrome?forum=vsdebug#5cd1aa58-d986-4d03-a10e-bf1fd62080a7
此后,我可以进行更好的调试,然后发现错误。
1- auth.service.ts。 throwError
中的Observable
函数
https://www.academind.com/learn/javascript/rxjs-6-what-changed/
return this.http.post<TokenResponse>(url, data)
.pipe(
map(res => {
let token = res && res.token;
if (token) {
this.setAuth(res);
return true;
}
else {
//failed login
return Observable.throwError('Unauthorized');
}
}),
catchError(error => {
//console.log(error);
return new Observable<any>(error);
})
);
2- TokenController Audiecnete
而非Audience
中的Typo错误
var token = new JwtSecurityToken(
issuer: Configuration["Auth:Jwt:Issuer"],
audience: Configuration["Auth:Jwt:Audience"],
claims: claims,
notBefore: now,
expires:
now.Add(TimeSpan.FromMinutes(tokenExpirationMins)),
signingCredentials: new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256)
);