Страница входа в клиент Angular 9
Я хочу отображать конкретное возвращаемое сообщение об ошибке в элементе <h4>
вместо общего сообщения, которое отображается в данный момент.
Примечание. Я обновил страницу, указав решение, которое собираюсь использовать.
<div class = "navbar bg-info mb-1">
<a class = "navbar-brand text-white">The ACTS Factory Authentication</a>
</div>
<!-- I want to put the specific error condition here -->
<h4 *ngIf = "showError" class = "p-2 bg-danger text-white">
<!-- Invalid username or password! --> {{theError}}
</h4>
<form novalidate #authForm = "ngForm" class = "m-3" title = "LoginForm">
<div class = "form-group">
<label>Name:</label>
<input #name = "ngModel" name = "name" class = "form-control"
[(ngModel)] = "authService.name" required />
<div *ngIf = "name.invalid" class = "text-danger">
Please enter your user name
</div>
</div>
<div class = "form-group">
<label>Password:</label>
<input type = "password" #password = "ngModel" name = "password"
class = "form-control" [(ngModel)] = "authService.password" required />
<div *ngIf = "password.invalid" class = "text-danger">
Please enter your password
</div>
</div>
<div class = "text-center pt-2">
<button type = "button" class = "btn btn-primary font-weight-bold" [disabled] = "authForm.invalid"
(click) = "login()">
Please Login
</button>
</div>
</form>
Угловой 9-компонентный
Я вхожу в систему из этого клиентского компонента Angular. Когда код состояния ответа равен 400 Bad Request, result
имеет значение false, и в элементе <h4>
отображается общее сообщение об ошибке. Здесь метод login()
подписывается на метод Login()
в репозитории службы аутентификации. Возвращенный объект ответа или свойство, содержащее текст ошибки, должен вернуться сюда, чтобы быть добавленным в HTML-отображение.
Примечание. Я обновил код решением, которое собираюсь использовать.
import { Component } from "@angular/core";
import { AuthenticationService } from "./authentication.service";
import { HttpErrorResponse } from "@angular/common/http";
@Component({
templateUrl: "authentication.component.html"
})
export class AuthenticationComponent {
showError: boolean = false;
theError?: string = null;
constructor(public authService: AuthenticationService) { }
login() {
// this.showError = false;
// this.authService.login().subscribe(result => { this.showError = !result });
// new Solution:
this.authService.login().subscribe(result => { /* success action */ this.showError = !result }, // if true result, "showError" = false
(err: HttpErrorResponse) => { /* error action */ console.error(err) },
() => { /* complete (after success OR error) action */
if (this.authService.theError != null) {
this.theError = this.authService.theError;
this.showError = true;
}})
}
}
Метод входа Angular 9 в репозиторий службы аутентификации клиента
Этот метод входа вызывает наблюдаемый метод источника данных login()
, определяет, был ли получен действительный (истинный или ложный) ответ, и сопоставляет возвращаемые свойства, содержащиеся в ответе, с локальными переменными. Примечание. Я обновил код решением, которое собираюсь использовать.
// new variable for solution
theError: string = null;
login(): Observable<boolean> {
this.authenticated = false;
return this.dataSource.login(this.userName, this.userPwd).pipe(
map(response => {
if (response) {
this.callbackUrl = null;
this.authenticated = true;
this.password = null
this.router.navigateByUrl(this.callbackUrl || "appmenu");
}
// new code for solution - to capture error from datasource response object
else {
this.theError = this.dataSource.loginError;
}
this.profileEmail = null;
this.profilePhone = null;
if (this.dataSource.teamUser) {
this.isTeamUser = this.dataSource.teamUser;
}
else {
this.isTeamUser = false;
}
return this.authenticated = true;
}),
catchError(e => {
this.authenticated = false;
[I have tried to capture the error text here]
return of(false);
}));
}
Метод входа в источник данных проверки подлинности клиента Angular 9
Это источник данных для клиента; он отправляет HTTP-запрос на сервер и получает HTTP-ответ. Он также сопоставляет свойства ответа с локальными переменными, определяет целевой URL-адрес и отслеживает необходимые заголовки. Примечание. Я обновил код решением, которое собираюсь использовать.
// new property in solution to contain login errors
_loginError?: string = "Server not ready - try again.";
public get loginError(): string {
return this._loginError;
}
public set loginError(newValue: string) {
this._loginError = newValue;
}
// end new property
auth_Header: HttpHeaders = new HttpHeaders();
auth_token: string = null;
login(theName: string, thePassword: string): Observable<boolean> {
return this.http.post<any>("/api/account/login",
{ name: theName, password: thePassword })
.pipe(map(response => {
// new solution code for capturing error and exiting if
// the login status code is 203, codes in 400 series do
// not logically track here.
this.loginError = response.LoginError;
if (!response.success) {
return false;
}
// end new code
this.auth_token = response.success ? response.token : null; // JWT token generated in server-side AccountController
this.auth_Header = this.auth_Header.set("Authorization", "Bearer<" + this.auth_token + ">");
this.authCookie.JWTauthcookie = this.auth_token; // save for the other datasources
this.loginTime = response.loginTime;
// to return user's registered email and phonenumber to client
this.profileEmail = "";
this.profileEmail = response.profileEmail;
this.profilePhone = "";
this.profilePhone = response.profilePhone;
}
this.isAuthenticated = true;
return response.success;
}));
Контроллер учетных записей ASP.NET Core MVC
Это контроллер ASP.NET Core MVC, который обрабатывает запрос на вход в систему, ищет в ASP.NET Core Identity имя пользователя и пароль (не показаны в коде) и возвращает код состояния 200 плюс объект JSON при успешном входе в систему. Теперь я возвращаю два конкретных состояния ошибки входа в систему (пользователь не найден или недействительный пароль), которые я хочу отобразить на клиенте после недействительной попытки входа в систему. Я попытался вернуть ошибки с OK
вместо BadRequest()
кода состояния 400. Но это бесполезно для клиента. Примечание. Я обновил код решением, которое собираюсь использовать.
Любые идеи будут оценены по достоинству. Спасибо.
[HttpPost("/api/account/login")]
public async Task<IActionResult> Login([FromBody] LoginViewModel creds)
{
LoginError = "";
bool loginResult = false;
object myReturnObject = new object();
if (ModelState.IsValid)
{
// go look for existing Identity user and try to sign in
loginResult = await DoLogin(creds);
if (loginResult)
{
myReturnObject = "{ " + '\n' + " " + '"' + "success" + '"' + ":" + '"' + signInResult.Succeeded.ToString() + '"' + "," + '\n' +
" " + '"' + "token" + '"' + ':' + '"' + bearerJWTokenString + '"' + "," + '\n' +
" " + '"' + "loginTime" + '"' + ':' + '"' + DateTime.Now.ToShortTimeString() + '"' + "," + '\n' +
" " + '"' + "profileEmail" + '"' + ':' + '"' + profileEmail + '"' + "," + '\n' +
" " + '"' + "profilePhone" + '"' + ':' + '"' + profilePhone + '"' + "," + '\n' +
" " + '"' + "team" + '"' + ':' + '"' + loggedInUserType.ToString() + '"' + "," + '\n' +
"}";
// good login returns this object as a Json file in
// the HTTP Response body
return Ok(myReturnObject);
}
else
{
// Solution: fixed Json object, and now if bad username or pwd.
// This returns http status code 203 plus the LoginError json object.
// It was returning "BadRequest(Json-formatted string)"
myReturnObject = "{" + '\n' + " " + '"' + "InvalidLogin" + '"' + ':' + '"' + "True" + '"' + "," +
'\n' + " " + '"' + "LoginError" + '"' + ':' + '"' + LoginError + '"' +
'\n' + "}";
return StatusCode(203, myReturnObject);
}
}
// bad model state returns - http error 400 Bad Request
return BadRequest(ModelState.ValidationState.ToString());
}
Снимок экрана с исходной ошибкой, отображаемой в клиенте:
Теперь решение предоставляет конкретную ошибку, когда код состояния 203 возвращается с объектом Json:
@YongShun Спасибо, что заметили недостающую запятую между свойствами. Я думаю ты прав. Мне следовало создать объект и установить его в свою строку, а затем вернуть объект в качестве параметра вместо строки в формате Json. Как я сделал в ответе с хорошим результатом с «MyReturnObject».
.subscribe(
data => {/* success action*/},
(error: HttpErrorResponse) => {/* error action */ console.error(error)},
() => {/* complite (after success OR error) action */}
)
Мне не удалось вернуть состояние ошибки с кодом состояния 400 в средний раздел «Ошибка» подписки, но с помощью кода возврата 203 я смог вернуть состояние ошибки и зафиксировать его, чтобы сделать состояние ошибки более конкретным. для пользователя. Мое приложение является частным, а не общедоступным, поэтому я бы не рекомендовал так подробно относиться к ошибкам на коммерческом общедоступном сайте. Спасибо.
Я предполагаю, что для фиксации состояния ошибки 400 Bad Request в компоненте Angular 9 его метод должен быть подписан на метод http источника данных, а не на метод репозитория службы, который отображает свойства ответа из метода http источника данных. Хм?
Кроме того, моя служба аутентификации и источник данных относятся к типам Observable<boolean>. Таким образом, они возвращают компоненту только истинное или ложное значение. Я думаю, мне придется перепроектировать эти методы, чтобы они были Observable<string> или каким-либо типом сущности, чтобы возвращать текст ошибки.
Не создавайте JSON вручную на стороне API, это похоже на то, что ваш API возвращает ответ в виде строки вместо JSON (хотя результат выглядит как JSON). Кроме того, вы можете видеть, что результат вашего ответа неверен: в JSON отсутствует запятая. Верните ответ как объект.