Angular 11-使用PHP的JWT身份验证示例和教程
Angular 11 - JWT Authentication Example & Tutorial With PHP
通常,通过输入用户名,电子邮件地址和/或密码来对用户进行身份验证,然后授予其访问各种资源或服务的权限。身份验证本身就依赖于维护用户的状态。这似乎违背了HTTP作为无状态协议的基本属性。
您的Angular应用程序将与生成令牌的后端进行通信。然后,Angular应用程序可以将令牌作为“授权”标头发送到后端,以显示它们已通过身份验证。 JWT应由后端检查,并应根据其有效性授予访问权限。
本教程将逐步指导您在Angular 11应用程序中开发和实现基于JWT的身份验证的过程。本教程通过使用PHP开发后端服务使您更进一步。
执行
在这一部分中,我将向您展示如何将PHP与Angular 11客户端结合使用以实现JWT身份验证。即使原理很明确,实现也必须熟悉安全最佳实践。
此处提供的示例是不完整的,并且缺少生产服务器将具有的若干功能。因此,我不建议在本教程中将源代码用于生产目的。
我假设您熟悉MySQL,Angular和PHP。您还应该在开发环境中安装composer。
步骤1:数据库准备
如果您具有所有先决条件,那么让我们开始构建一个MySQL数据库。我们将使用服务器随附的MySQL客户端。
打开终端并键入以下命令以启动客户端:
$ mysql -u root -p
根据您的MySQL配置,在出现提示时输入密码。
在显示的窗口上,运行以下命令来创建数据库。
mysql> create database jwt-database;
在我们之前创建的jwt-database中,创建一个表jwt-users,如下所示:
mysql> use jwt-database;
mysql> create table `jwt-users` (
`user_id` int auto_increment primary key,
`fullname` varchar(40) ,
`username` varchar(40) ,
`email_address` varchar(40) unique,
`password` varchar(40) not null,
现在,通过运行以下命令,将cd放入我们先前创建的目录中:
cd jwt-server
注意:根据您的开发环境,此路径可能会有所不同。
连接到数据库
在您的工作目录中,在tokens-api目录中创建一个文件夹db_configurations。
cd tokens-api && mkdir configurations
然后,
cd configurations
conn = null;
try
{
$this->connection = new PDO("mysql:host=" . $this->db_host . ";dbname=" . $this->db_name, $this->db_user, $this->db_password);
$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo "Error " . $e->getMessage();
}
return $this->connect;
}
}
步骤2:安装PHP令牌生成器软件包
PHP具有JWT库,该库可用于生成身份验证令牌,以标识访问后端服务的客户端。
要在系统中安装此PHP库,您需要安装一个作曲家。
您可以通过运行以下命令来验证其安装:
composer -v
现在,通过运行以下命令继续并导入库:
$ composer require firebase/php-jwt
为了允许我们的PHP后端和angular应用程序之间进行通信,我们需要设置CORS标头。
让我们继续创建文件header.php,并添加以下CORS脚本:
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Methods: POST, PUT, DELETE, UPDATE");
header("Access-Control-Allow-Origin: * ");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
步骤3:用户注册API端点
现在我们的系统中已经有了php-jwt库,让我们继续创建一个简单的注册系统。在当前目录中,添加以下代码行。
db_connect();
$api_data = json_decode(file_get_contents("php://input"));
$full_name = $api_data->full_name;
$email_address = $api_data->email;
$password = $api_data->password;
$query = "INSERT INTO " jwt_users . "
SET full_name = :fname,
email = :emailAdress,
password = :pwd";
$stmt = $conn->prepare($query);
$stmt->bindParam(':fname',$full_name)
$stmt->bindParam(':email', $email_address);
$stmt->bindParam(':password', $password1);
$stmt->execute();
?>
用户登录API端点
在tokens-api目录中,创建一个signin.php文件,并添加以下代码以检查客户端资格以访问我们的后端服务。
要验证用户凭据并将JSON Web令牌返回给客户端,请使用以下代码在tokens-api目录中构建一个signin.php文件脚本:
db_connect();
$api_data = json_decode(file_get_contents("php://input"));
$user_email = $api_data->email_address;
$password = $api_data->password;
$table = 'Users';
$sql = "SELECT user_id,first_name, last_name,`password` FROM " . $table . " WHERE email_address =:email LIMIT 0,1";
$stmt = $conn->prepare( $query );
$stmt->bindParam(':email', $email_address);
$stmt->execute();
$numOfRows = $stmt->rowCount();
if($numOfRows) > 0){
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$user_id = $row['id'];
$first_name = $row['first_name'];
$last_name = $row['last_name'];
$pass = $row['password'];
if(password_verify($password, $pass))
{
$secret_key = "MillerJumaWilliam";
$issuer_claim = "localhost";
$audience_claim = "THE_AUDIENCE";
$issuedat_claim = time(); // time issued
$notbefore_claim = $issuedat_claim + 10;
$expire_claim = $issuedat_claim + 60;
$token = array(
"iss" => $issuer_claim,
"aud" => $audience_claim,
"iat" => $issuedat_claim,
"nbf" => $notbefore_claim,
"exp" => $expire_claim,
"data" => array(
"id" => $id,
"firstName" => $first_name,
"lastName" => $last_name,
"userEmail" => $email_address
));
$jwtValue = JWT::encode($token, $secret_key);
echo json_encode(
array(
"message" => "success",
"token" => $jwtValue,
"email_address" => $email_address,
"expiry" => $expire_claim
));
}
else{
echo json_encode(array("success" => "false"));
}
}
?>
您可以根据需要描述令牌的数据结构,但是应正确指定某些保留的JWT语句,因为它们会影响令牌的有效性。
JWT :: encode()方法将PHP数组转换为JSON格式,对有效负载进行签名,然后对最终令牌进行编码,然后再将其发送到客户端(即浏览器)。
为了注册和登录用户,我们现在有两个RESTful端点。让我们通过在'token-apifolder中运行以下命令来测试我们的端点是否正常工作。
'token-apifolder.
bash
cd tokens-api && php -S 127.0.0.1:8000 // to start our development server
`
现在,我们已经有了带有JWT令牌的功能齐全的REST API,让我们继续创建角度项目。
设置角度项目以使用PHP身份验证端点
值得注意的是,本教程不会教您如何设置角度项目,有关更多信息,请访问角度文档。
在新的角度项目中,运行以下命令以创建authService服务:
bash
$ ng generate service auth
我们将使用该服务来登录和注销用户。让我们将以下代码添加到我们的身份验证服务中。
ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class AuthService {
public baseUrl = "localhost:8000";
private loggedUserSubject: BehaviorSubject;
public loggedInUser: Observable;
constructor(private httpClient: HttpClient) {
getLoggedUser = JSON.parse(localStorage.getItem('loggedInUser'));
this.loggedUserSubject = new BehaviorSubject(this.getLoggedUser));
this.loggedInUser = this.loggedUserSubject.asObservable();
}
loginUser(emailAddress: string, password: string) {
return this.http.post(${baseUrl}/, { emailAddress, password })
.pipe(map(response=> {
localStorage.setItem('loggedInUser', JSON.stringify(response));
this.loggedUserSubject.next(response);
console.log(response);
return response;
}));
}
logoutUser() {
localStorage.removeItem('loggedInUser');
this.loggedUserSubject.next(null);
}
public get loggedInUserValue(){
return this.loggedUserSubject.value;
}
}
在上面的auth服务中,当用户登录和退出系统时,RxJS主题和可观察对象用于存储当前用户。
设置登录组件
现在,我们已经有了将HTTP请求发送到PHP端点的服务,让我们继续运行下面的命令,创建一个登录组件来测试我们的代码:
bash
$ ng g c login
在新的组件模板中,复制并粘贴以下代码:
html
Authentication Form
Email Address
我们上面创建的表单使用了Angular的Reactive Forms模块。触发点击事件后,用户信息就会发送到我们的组件。
准备好我们的登录模板后,在yourlogin.compnent.ts文件中,添加以下代码段以获取用户输入。
正是在此脚本中,捕获了用户的值,然后将其发送到我们之前通过auth服务创建的API服务。
ts
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { AuthService } from './service/auth.service'; @Component({ templateUrl: 'login.component.html' }) export class LoginComponent implements OnInit { signinForm: FormGroup; constructor( private fb: FormBuilder, private authService: AuthService ) { } ngOnInit() { this.signinForm = this.fb.group({ email: [null, [Validators.required, Validators.email]], password: [null, Validators.required] }); } get form() { return this.signinForm.controls; } onSubmit() { this.authService.loginUser(this.form.email.value, this.form.password.value) .subscribe( data => { console.log(data); }, error => { console.log(error); }); }
将登录令牌存储在本地存储中
Angular附带了HTTP拦截器。因此,任何请求都将传递一个令牌,该令牌将在我们的后端用于验证用户的有效性。
让我们继续运行以下命令,为我们的应用程序AuthInterceptor创建一个拦截器:
bash
$ ng g interceptor auth
ts
...
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from './service/auth.module';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent> {
let loggedInUser = this.authService.currentUserValue;
token = JSON.parse(localStorage.getItem(user.token));
if (token) {
request = request.clone({
setHeaders: {
Authorization:Bearer ${token}
}
});
}
return next.handle(request);
}
}
现在,让我们继续将此脚本添加到我们的app.module.ts中,以确保克隆我们发送的所有请求并附加令牌。
ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AppComponent } from './app.component';
import { appRoutingModule } from './app.routing';
import { AuthInterceptor} from 'helpers/AuthInterceptor';
import { DashboardComponent } from './dashboard';
import { LoginComponent } from './login';
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
HttpClientModule,
appRoutingModule
],
declarations: [
AppComponent,
DashboardComponent,
LoginComponent
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true
],
bootstrap: [AppComponent]
})
export class AppModule { }
好吧,让我们通过运行以下命令来启动我们的角度应用程序:
bash
ng serve --open //starts on port 4200 by default unless you specify otherwise
现在,当生成的令牌存储在浏览器的本地存储中时,您可以向我们的PHP终结点发出请求并登录。
结论
在本教程中,我们学习了如何在具有PHP RESTful API的Angular 11应用程序中使用JWT身份验证。我们还在Angular应用程序中实现了其他身份验证策略,例如令牌身份验证。
快乐的编码。
转:https://dev.to/jumamiller/angular-11-jwt-authentication-example-tutorial-with-php-2d7d
相关文章