如何在后端验证表单字段并在Angular7上显示它们?

时间:2019-05-14 11:53:51

标签: angular hibernate spring-boot

我想用弹簧靴子写我的应用程序后端,而用尖角写我的应用程序前端。我想检查后端的表单字段中的信息以确保安全。为了尝试这项工作,我首先创建了一个名为Visitor.java的模型,所有代码如下。

Visitor.java

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;

public class Visitor {

    @NotNull(message = "This field cannot be null.")
    @Email(message = "Invalid.")
    private String email;

    @NotNull(message = "This field cannot be null.")
    private String password;

    public Visitor() {
    }

    public Visitor(String email, String password) {
        this.email = email;
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Visitor{" +
                "email='" + email + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

SignIn.java(RestController)

import com.demotest.example.demotest.model.Visitor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api")
@CrossOrigin
public class Sign {

    @PostMapping("/signin")
    public ResponseEntity<Object> signIn(@RequestBody @Valid Visitor visitor, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            System.err.println("error!");
            Map<String, String> errors = new HashMap<>();
            for (FieldError error:bindingResult.getFieldErrors()){
                errors.put(error.getField(), error.getDefaultMessage());
            }
            return new ResponseEntity<>(errors, HttpStatus.NOT_ACCEPTABLE);
        }
        System.err.println("nice!");
        return new ResponseEntity<>(HttpStatus.OK);
    }

}

sign.in.component.ts

import { Component, OnInit } from '@angular/core';
import {HttpClient} from "@angular/common/http";

@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.component.html',
  styleUrls: ['./sign-in.component.css']
})
export class SignInComponent implements OnInit {

  model:loginViewModel = {
    email:'',
    password:''
  };

  sendLoginViewModel():void{
    //alert(this.model.email);
    let url = "http://localhost:7070/api/signin";

    this.http.post(url, this.model).subscribe(
      res => {
        //location.reload();

      },
      err => {
                   console.log(err);
      }
    );
  }

  constructor(private http: HttpClient) { }

  ngOnInit() {
  }
}

export interface loginViewModel{
  email:string;
  password:string;
}

sign-in.component.html

<div class="container mt-5">
  <div class="col-lg-4 card mx-auto px-0">
    <div class="card-body">

      <div class="row mt-4">
        <div class="col mx-auto text-center" style="font-size: 23.1px; padding-right: 37px; padding-left: 37px;">
          www.sss.com
        </div>
      </div>

      <div class="row">
        <div class="col mx-auto text-center" style="font-size: 40px; padding-right: 37px; padding-left: 37px;">
          Welcome
        </div>
      </div>

      <form #f="ngForm" (submit)="sendLoginViewModel()">

        <div class="row">
          <div class="col mt-5 px-0 mx-auto">
            <mat-form-field appearance="outline" class="col mx-auto">
              <mat-label>Email</mat-label>
              <input matInput placeholder=""
                     name="email"
                     [(ngModel)]="model.email"
                     #name="ngModel"/>
              <mat-icon matSuffix>email</mat-icon>
            </mat-form-field>

<!--            todo: Error div i will be added here.-->

          </div>
        </div>

        <div class="row">
          <div class="col px-0 mx-auto">
            <mat-form-field appearance="outline" class="col mx-auto">
              <mat-label>Password</mat-label>
              <input matInput placeholder="" name="password" [(ngModel)]="model.password">
              <mat-icon matSuffix>lock</mat-icon>
            </mat-form-field>

            <!--            todo: Error div i will be added here.-->

          </div>
        </div>

        <button type="submit" class="col py-1 mx-auto mt-3 mb-3" mat-flat-button color="primary">
          Login
        </button>
      </form>
    </div>
  </div>
</div>

console.log(err);

我想在html页面上使用以下error: {email: "Invalid."}email是错误的标题,而"Invalid."是错误消息的内容。由于这些日志字段是由后端发送的,因此它们是安全信息,我想在html页面上使用它们。如何在中写出错误消息中是否有电子邮件,请打印该消息。吗?

HttpErrorResponse {headers: HttpHeaders, status: 406, statusText: "OK", url: "http://localhost:7070/api/signin", ok: false, …}
error: {email: "Invalid."}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure response for http://localhost:7070/api/signin: 406 OK"
name: "HttpErrorResponse"
ok: false
status: 406
statusText: "OK"
url: "http://localhost:7070/api/signin"
__proto__: HttpResponseBase

目前,我可以在春季在后台进行验证,但是无法在sign-in.component.html上打印错误消息。我很困惑要打印传入的错误信息。如何打印错误消息?

1 个答案:

答案 0 :(得分:0)

一个非常简单的解决方案是订阅该错误,然后使用ngif。

error: any;

sendLoginViewModel():void{

    let url = "http://localhost:7070/api/signin";

    this.http.post(url, this.model).subscribe(
      res => {
        //location.reload();

      },
      err => {
    this.error = err.message
      }
    );
  }


        <div *ngIf="error" class="alert alert-danger">
            {{error}}
        </div>

但是我建议使用反应性表单来创建表单组,以设置登录信息所需的验证器。然后,如果服务器返回错误,则可以将窗体控件设置为dirty以激活ui错误状态。您可以为电子邮件设置validators.pattern,然后让客户端首先进行基本的电子邮件验证,如下所示:

this.validations_form = this.formBuilder.group({

    email: new FormControl('', Validators.compose([
        Validators.required,
        Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
    ]))
});


<div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)" class="alert alert-danger">
            <div *ngIf="angForm.controls['email'].errors.required">
            A valid email is required.
          </div>
        </div>

我也强烈建议研究一个更复杂的身份验证示例,该示例使用可注入的Auth Guard服务和警报组件。

这是一个很好的例子: https://jasonwatmore.com/post/2018/10/29/angular-7-user-registration-and-login-example-tutorial