KeyCloak PT 2による角度とクォークの固定
71474 ワード
以前の記事では、KeyCloakのログインとロールの認識を可能にする初期ユーザーインターフェイスを作成しました.次のステップは、安全で、ベースのサービスを提供するバックエンドサービスにこれを配線することです.
この記事のコードはGitHubにあります. Petstore UI Petstore API 典型的なシナリオでは、2種類の異なるサービスを実装します. 店舗従業員が従業員の特定機能を利用するサービス 顧客特有のサービス また、複数のレベルの統合を実装します.今のところ、我々は簡単なものから始め、単一のクォークマイクロサービスを作成し、我々が作成したロールを管理します.
だから、それをキックしましょう!
APIクライアントの作成
ゲット/ペッツ 両方のグループ(店従業員と顧客)によってアクセス可能 ゲット/セールス 店員だけがアクセスできる ゲット/リワード ログインしている顧客によってアクセス可能 プロジェクトでは、いくつかのリソースと表現を作成します.
資源ジャバ
トランザクション.ジャバ
APIのセキュリティー保護
顧客と従業員のためにペットをリストするために、新しい見解を加えてください 従業員のためにリストを売るために新しい見解を加えてください 顧客のための報酬をリストに新しいビューを追加 別のロールを試してみないと不正行為を回避し、バイパスを確認するAuthGuardに追加
新しいビューを作成し始めましょう!
新しいPetSponent , SalesComoponent , RewardsComoponentを作成して起動します.
倉庫 オーサガード
オリジナルのエンドポイントに基づいて、3つの関数を作成します. ストア.サービスTS
販売.コンポーネント.TS
モデルクラスの構造のソースコードを見ることができます.
charleneマスターズとしてログインして、解決策を見ましょう
ご覧の通り、割り当てられたロールに基づいた結果が得られます.しかし、どのようにDOS APIはどのような役割をユーザーが知っている?開発コンソールを開き、ネットワークタブを選択した場合は、サーバーにXHR要求を見てください.
見てみると、APIリクエストの一部として渡されるベアラートークンを見ることができます!
なぜなら、私たちは
ガードの設定
この記事のコードはGitHubにあります.
だから、それをキックしましょう!
APIクライアントの作成
KeyCloak Admin UIに戻り、使用するAPIの新しいクライアントを作成します.
クライアントに移動しCreate
:
クライアントが作成されると、ロールタブに移動してクライアントが想定している役割を作成します.
そして、我々は前の記事のようにこれらの背中を我々のユーザーに写像したいです.
グループへ移動します.api-employee
役割
同じことをするapi-customer
役割
次に、私たちのサービスAPIで仕事を始めたいです.
サービスの作成
私たちはゼロから始め、標準的なクォークサービスを作ります.
$ mvn io.quarkus:quarkus-maven-plugin:1.7.2.Final:create \
-DprojectGroupId=com.brightfield.streams \
-DprojectArtifactId=petstore-api
生命をより簡単にするいくつかの依存関係は以下を含みます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
我々のアプリケーションを確保する前に、何かを実行してみましょう.
エンドポイントの実装
3つのエンドポイントが実装されます.
私たちはゼロから始め、標準的なクォークサービスを作ります.
$ mvn io.quarkus:quarkus-maven-plugin:1.7.2.Final:create \
-DprojectGroupId=com.brightfield.streams \
-DprojectArtifactId=petstore-api
生命をより簡単にするいくつかの依存関係は以下を含みます: <dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
我々のアプリケーションを確保する前に、何かを実行してみましょう.エンドポイントの実装
3つのエンドポイントが実装されます.
資源ジャバ
package com.cloudyengineering.pets;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
@Path("/v1/pets")
@Produces("application/json")
public class PetResource {
@GET
public Response getPets() {
List<Pet> pets = new ArrayList<>();
return Response.ok(pets).build();
}
}
販売資源ジャバpackage com.cloudyengineering.pets;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
@Path("/v1/admin")
@Produces("application/json")
public class SalesResource {
@GET
public Response getSales() {
List<Transaction> transactions = new ArrayList<>();
return Response.ok(transactions).build();
}
}
ペットジャバpackage com.cloudyengineering.pets;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Pet {
@JsonProperty("pet_id")
private Integer petId;
@JsonProperty("pet_type")
private String petType;
@JsonProperty("pet_name")
private String petName;
@JsonProperty("pet_age")
private Integer petAge;
public Integer getPetId() {
return petId;
}
public void setPetId(Integer petId) {
this.petId = petId;
}
public String getPetType() {
return petType;
}
public void setPetType(String petType) {
this.petType = petType;
}
public String getPetName() {
return petName;
}
public void setPetName(String petName) {
this.petName = petName;
}
public Integer getPetAge() {
return petAge;
}
public void setPetAge(Integer petAge) {
this.petAge = petAge;
}
}
トランザクション.ジャバpackage com.cloudyengineering.pets;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Transaction {
@JsonProperty("txn_id")
private String transactionId;
@JsonProperty("txn_amount")
private Double transactionAmount;
@JsonProperty("txn_date")
private Date transactionDate;
@JsonProperty("txn_method")
private String transactionMethod;
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public Double getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(Double transactionAmount) {
this.transactionAmount = transactionAmount;
}
public Date getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(Date transactionDate) {
this.transactionDate = transactionDate;
}
public String getTransactionMethod() {
return transactionMethod;
}
public void setTransactionMethod(String transactionMethod) {
this.transactionMethod = transactionMethod;
}
}
ご覧の通り、これらは単なるプレースホルダですので、いくつかのロジックを埋めましょう. @GET
public Response getPets() {
List<Pet> pets = new ArrayList<>();
Pet pet1 = new Pet();
pet1.setPetId(1);
pet1.setPetAge(6);
pet1.setPetName("Oliver");
pet1.setPetType("Dog");
Pet pet2 = new Pet();
pet2.setPetId(2);
pet2.setPetAge(1);
pet2.setPetName("Buster");
pet2.setPetType("Cat");
Pet pet3 = new Pet();
pet3.setPetId(3);
pet3.setPetAge(2);
pet3.setPetName("Violet");
pet3.setPetType("Bird");
pets = Lists.asList(pet1, new Pet[]{pet2, pet3});
return Response.ok(pets).build();
}
トランザクションリソース.ジャバ @GET
public Response getSales() {
List<Transaction> transactions = new ArrayList<>();
Transaction txn1 = new Transaction();
txn1.setTransactionId(UUID.randomUUID().toString());
txn1.setTransactionAmount(12.56);
txn1.setTransactionDate(Date.from(Instant.now()));
txn1.setTransactionMethod("Cash");
Transaction txn2 = new Transaction();
txn2.setTransactionId(UUID.randomUUID().toString());
txn2.setTransactionAmount(56.16);
txn2.setTransactionDate(Date.from(Instant.now()));
txn2.setTransactionMethod("Credit Card");
Transaction txn3 = new Transaction();
txn3.setTransactionId(UUID.randomUUID().toString());
txn3.setTransactionAmount(88.99);
txn3.setTransactionDate(Date.from(Instant.now()));
txn3.setTransactionMethod("Credit Card");
transactions = Lists.asList(txn1, new Transaction[]{txn2, txn3});
return Response.ok(transactions).build();
}
すぐにそれをテストしましょう!$ ./mvnw quarkus:dev
Listening for transport dt_socket at address: 5005
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-10-04 18:30:09,620 INFO [io.quarkus] (Quarkus Main Thread) pet-store-api 1.0-SNAPSHOT on JVM (powered by Quarkus 1.8.1.Final) started in 3.296s. Listening on: http://0.0.0.0:
8080
2020-10-04 18:30:09,622 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2020-10-04 18:30:09,622 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, resteasy-jackson]
$ http :8080/v1/pets
HTTP/1.1 200 OK
Content-Length: 188
Content-Type: application/json
[
{
"pet_age": 6,
"pet_id": 1,
"pet_name": "Oliver",
"pet_type": "Dog"
},
{
"pet_age": 1,
"pet_id": 2,
"pet_name": "Buster",
"pet_type": "Cat"
},
{
"pet_age": 2,
"pet_id": 3,
"pet_name": "Violet",
"pet_type": "Bird"
}
]
$ http :8080/v1/admin
HTTP/1.1 200 OK
Content-Length: 357
Content-Type: application/json
[
{
"txn_amount": 12.56,
"txn_date": 1601862235453,
"txn_id": "cb09b51d-541a-45b5-9c27-13a09b480dfd",
"txn_method": "Cash"
},
{
"txn_amount": 56.16,
"txn_date": 1601862235454,
"txn_id": "2895fe10-31ae-417a-8d7d-28ccdf0fa08b",
"txn_method": "Credit Card"
},
{
"txn_amount": 88.99,
"txn_date": 1601862235454,
"txn_id": "afbec85c-b919-40e4-9b02-9e5779534b0b",
"txn_method": "Credit Card"
}
]
うーんそれらの日付はあまりにも友好的に見えない、それらを変更しましょうトランザクション.ジャバ
@JsonProperty("txn_date")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
private Date transactionDate;
そして再び.$ http :8080/v1/admin
HTTP/1.1 200 OK
Content-Length: 381
Content-Type: application/json
[
{
"txn_amount": 12.56,
"txn_date": "05-10-2020 01:46:17",
"txn_id": "8d5e875b-06ec-4cf6-b357-4e14525b831c",
"txn_method": "Cash"
},
{
"txn_amount": 56.16,
"txn_date": "05-10-2020 01:46:17",
"txn_id": "5764bef6-1c78-4efd-8016-119759b263c5",
"txn_method": "Credit Card"
},
{
"txn_amount": 88.99,
"txn_date": "05-10-2020 01:46:17",
"txn_id": "67a5f766-4a9f-4fa4-8e22-59ecf9171e55",
"txn_method": "Credit Card"
}
]
いいねそれは動作しますが、まだ非常に安全ではないです.APIのセキュリティー保護
2つの依存関係があります.
POMXML
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId>
</dependency>
</dependencies>
アプリケーション.プロパティ
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/petshop-realm
quarkus.oidc.client-id=pet-store-api
quarkus.oidc.credentials.secret=itsasecret
quarkus.oidc.authentication.scopes=profile
quarkus.http.cors.origins=http://localhost:4200
quarkus.http.cors.methods=GET,OPTIONS
quarkus.http.cors=true
ご覧の通り、クライアントIDを宣言しましたpetshop-api
しかし、我々も秘密を供給しましたitsasecret
, が設定されていることを確認しましょう!
移動先:クライアント->ペットストアAPI
アクセスタイプをbearer only
とヒットを保存します.あなたは、上記のタブを見るべきです!
次のタブの資格情報に移動し、クライアントの秘密を参照してください.
この生成された秘密をペットストアAPIにコピーしましょう.
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/petshop-realm
quarkus.oidc.client-id=pet-store-api
quarkus.oidc.credentials.secret=05da844f-c975-4571-8767-cbc8078e7b64
quarkus.oidc.authentication.scopes=profile
APIを今すぐ実行してみて、それにアクセスしてみると、私たちは不正な401を得るべきです.
$ http :8080/v1/admin
HTTP/1.1 200 OK
Content-Length: 381
Content-Type: application/json
[
{
"txn_amount": 12.56,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "a19f4089-5f20-4355-ab4a-a18367347d6d",
"txn_method": "Cash"
},
{
"txn_amount": 56.16,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "6457746c-9c07-4cea-b8c5-fb30dc4e2f3d",
"txn_method": "Credit Card"
},
{
"txn_amount": 88.99,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "09125408-0787-41d0-9976-8e56c5937bb3",
"txn_method": "Credit Card"
}
]
ちょっと待って!それは違いますああ覚えて、我々のエンドポイントの周りのセキュリティを指定していない!コードを更新しましょう
販売資源ジャバ
@Path("/v1/admin")
@Produces("application/json")
public class SalesResource {
@GET
@RolesAllowed({"api-employee"})
public Response getSales() {
List<Transaction> transactions;
Transaction txn1 = new Transaction();
txn1.setTransactionId(UUID.randomUUID().toString());
txn1.setTransactionAmount(12.56);
txn1.setTransactionDate(Date.from(Instant.now()));
txn1.setTransactionMethod("Cash");
Transaction txn2 = new Transaction();
txn2.setTransactionId(UUID.randomUUID().toString());
txn2.setTransactionAmount(56.16);
txn2.setTransactionDate(Date.from(Instant.now()));
txn2.setTransactionMethod("Credit Card");
Transaction txn3 = new Transaction();
txn3.setTransactionId(UUID.randomUUID().toString());
txn3.setTransactionAmount(88.99);
txn3.setTransactionDate(Date.from(Instant.now()));
txn3.setTransactionMethod("Credit Card");
transactions = Lists.asList(txn1, new Transaction[]{txn2, txn3});
return Response.ok(transactions).build();
}
}
資源ジャバ
@Path("/v1/pets")
@Produces("application/json")
public class PetResource {
@GET
@RolesAllowed({"api-customer"})
public Response getPets() {
List<Pet> pets;
Pet pet1 = new Pet();
pet1.setPetId(1);
pet1.setPetAge(6);
pet1.setPetName("Oliver");
pet1.setPetType("Dog");
Pet pet2 = new Pet();
pet2.setPetId(2);
pet2.setPetAge(1);
pet2.setPetName("Buster");
pet2.setPetType("Cat");
Pet pet3 = new Pet();
pet3.setPetId(3);
pet3.setPetAge(2);
pet3.setPetName("Violet");
pet3.setPetType("Bird");
pets = Lists.asList(pet1, new Pet[]{pet2, pet3});
return Response.ok(pets).build();
}
}
また試してみてください.
$ http :8080/v1/admin
HTTP/1.1 401 Unauthorized
Content-Length: 0
$ http :8080/v1/pets
HTTP/1.1 401 Unauthorized
Content-Length: 0
すごい!それは安全です!
準備は、ユーザーインターフェイスを統合するには?
セキュアサービスとUIの接続
ユーザーインターフェイスを訪問したとき、ユーザーのログイン作業を行うことができました.UIへの変更は以下のようになります.
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId>
</dependency>
</dependencies>
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/petshop-realm
quarkus.oidc.client-id=pet-store-api
quarkus.oidc.credentials.secret=itsasecret
quarkus.oidc.authentication.scopes=profile
quarkus.http.cors.origins=http://localhost:4200
quarkus.http.cors.methods=GET,OPTIONS
quarkus.http.cors=true
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/petshop-realm
quarkus.oidc.client-id=pet-store-api
quarkus.oidc.credentials.secret=05da844f-c975-4571-8767-cbc8078e7b64
quarkus.oidc.authentication.scopes=profile
$ http :8080/v1/admin
HTTP/1.1 200 OK
Content-Length: 381
Content-Type: application/json
[
{
"txn_amount": 12.56,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "a19f4089-5f20-4355-ab4a-a18367347d6d",
"txn_method": "Cash"
},
{
"txn_amount": 56.16,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "6457746c-9c07-4cea-b8c5-fb30dc4e2f3d",
"txn_method": "Credit Card"
},
{
"txn_amount": 88.99,
"txn_date": "06-10-2020 09:34:58",
"txn_id": "09125408-0787-41d0-9976-8e56c5937bb3",
"txn_method": "Credit Card"
}
]
@Path("/v1/admin")
@Produces("application/json")
public class SalesResource {
@GET
@RolesAllowed({"api-employee"})
public Response getSales() {
List<Transaction> transactions;
Transaction txn1 = new Transaction();
txn1.setTransactionId(UUID.randomUUID().toString());
txn1.setTransactionAmount(12.56);
txn1.setTransactionDate(Date.from(Instant.now()));
txn1.setTransactionMethod("Cash");
Transaction txn2 = new Transaction();
txn2.setTransactionId(UUID.randomUUID().toString());
txn2.setTransactionAmount(56.16);
txn2.setTransactionDate(Date.from(Instant.now()));
txn2.setTransactionMethod("Credit Card");
Transaction txn3 = new Transaction();
txn3.setTransactionId(UUID.randomUUID().toString());
txn3.setTransactionAmount(88.99);
txn3.setTransactionDate(Date.from(Instant.now()));
txn3.setTransactionMethod("Credit Card");
transactions = Lists.asList(txn1, new Transaction[]{txn2, txn3});
return Response.ok(transactions).build();
}
}
@Path("/v1/pets")
@Produces("application/json")
public class PetResource {
@GET
@RolesAllowed({"api-customer"})
public Response getPets() {
List<Pet> pets;
Pet pet1 = new Pet();
pet1.setPetId(1);
pet1.setPetAge(6);
pet1.setPetName("Oliver");
pet1.setPetType("Dog");
Pet pet2 = new Pet();
pet2.setPetId(2);
pet2.setPetAge(1);
pet2.setPetName("Buster");
pet2.setPetType("Cat");
Pet pet3 = new Pet();
pet3.setPetId(3);
pet3.setPetAge(2);
pet3.setPetName("Violet");
pet3.setPetType("Bird");
pets = Lists.asList(pet1, new Pet[]{pet2, pet3});
return Response.ok(pets).build();
}
}
$ http :8080/v1/admin
HTTP/1.1 401 Unauthorized
Content-Length: 0
$ http :8080/v1/pets
HTTP/1.1 401 Unauthorized
Content-Length: 0
ユーザーインターフェイスを訪問したとき、ユーザーのログイン作業を行うことができました.UIへの変更は以下のようになります.
ビューの作成
新しいビューを作成し始めましょう!
新しいPetSponent , SalesComoponent , RewardsComoponentを作成して起動します.
$ ng g c pet
CREATE src/app/pet/pet.component.css (0 bytes)
CREATE src/app/pet/pet.component.html (18 bytes)
CREATE src/app/pet/pet.component.spec.ts (605 bytes)
CREATE src/app/pet/pet.component.ts (263 bytes)
UPDATE src/app/app.module.ts (947 bytes)
$ ng g c sales
CREATE src/app/sales/sales.component.css (0 bytes)
CREATE src/app/sales/sales.component.html (20 bytes)
CREATE src/app/sales/sales.component.spec.ts (619 bytes)
CREATE src/app/sales/sales.component.ts (271 bytes)
UPDATE src/app/app.module.ts (1025 bytes)
$ ng g c rewards
CREATE src/app/rewards/rewards.component.css (0 bytes)
CREATE src/app/rewards/rewards.component.html (22 bytes)
CREATE src/app/rewards/rewards.component.spec.ts (633 bytes)
CREATE src/app/rewards/rewards.component.ts (279 bytes)
UPDATE src/app/app.module.ts (1111 bytes)
$ ng g guard auth
? Which interfaces would you like to implement? CanActivate
CREATE src/app/auth.guard.spec.ts (331 bytes)
CREATE src/app/auth.guard.ts (457 bytes)
私はMVCアプローチで完全には行かないので、異なるAPIを呼び出すためのサービスを1つ作成します.$ ng g s store
CREATE src/app/store.service.spec.ts (352 bytes)
CREATE src/app/store.service.ts (134 bytes)
つの主要分野に焦点を合わせましょう倉庫
オリジナルのエンドポイントに基づいて、3つの関数を作成します.
getPets(): Observable<Pet[]>
getSales(): Observable<Transaction[]>
getRewards(): Observable<Reward[]>
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Pet, Reward, Transaction } from './_model';
import { environment as env } from '../environments/environment';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class StoreService {
constructor(private http : HttpClient) { }
getPets(): Observable<Pet[]> {
const uri = `${env.api_host}/v1/pet`;
return this.http.get<Pet[]>(uri);
}
getSales(): Observable<Transaction[]> {
const uri = `${env.api_host}/v1/sales`;
return this.http.get<Transaction[]>(uri);
}
getRewards(): Observable<Reward[]> {
const uri = `${env.api_host}/v1/rewards`;
return this.http.get<Reward[]>(uri);
}
}
コンポーネントにサービスを提供し、結果を出力しましょう.販売.コンポーネント.TS
import { Component, OnInit } from '@angular/core';
import { StoreService } from '../store.service';
import { map, catchError } from 'rxjs/operators';
import { Transaction } from '../_model';
import { of } from 'rxjs';
@Component({
selector: 'app-sales',
templateUrl: './sales.component.html',
styleUrls: ['./sales.component.css']
})
export class SalesComponent implements OnInit {
sales: Transaction[];
constructor(private store: StoreService) { }
ngOnInit(): void {
const sale$ = this.store.getSales().pipe(
map(results => {
this.sales = results;
}),
catchError(error => {
console.log(error);
return of([]);
})
);
sale$.subscribe(data => data);
}
}
販売.コンポーネント.HTML<p>sales works!</p>
<table>
<tr>
<th>Transaction ID</th>
<th>Transaction Date</th>
<th>Transaction Amount</th>
<th>Payment Method</th>
</tr>
<tr *ngFor="let sale of sales">
<td>{{sale.txn_id}}</td>
<td>{{sale.txn_date}}</td>
<td>{{sale.txn_amount}}</td>
<td>{{sale.txn_method}}</td>
</tr>
<tr *ngIf="sales === undefined">
<td colspan="4">No data</td>
</tr>
</table>
ペットコンポーネント.TSimport { Component, OnInit } from '@angular/core';
import { StoreService } from '../store.service';
import { map } from 'rxjs/operators';
import { Reward } from '../_model';
@Component({
selector: 'app-rewards',
templateUrl: './rewards.component.html',
styleUrls: ['./rewards.component.css']
})
export class RewardsComponent implements OnInit {
rewards: Reward[];
constructor(private store: StoreService) { }
ngOnInit(): void {
this.store.getRewards().pipe(
map(results => {
this.rewards = results;
})
);
}
}
ペットコンポーネント.HTML<p>pet works!</p>
<table>
<tr>
<th>Pet ID</th>
<th>Pet Type</th>
<th>Pet Age</th>
<th>Pet Name</th>
</tr>
<tr *ngFor="let pet of pets">
<td>{{pet.pet_id}}</td>
<td>{{pet.pet_type}}</td>
<td>{{pet.pet_age}}</td>
<td>{{pet.pet_name}}</td>
</tr>
<tr *ngIf="pets === undefined">
<td colspan="4">No data</td>
</tr>
</table>
見ることができるように、私たちはenvironment
それから我々のURIをオブジェクト化して、構築してください.モデルクラスの構造のソースコードを見ることができます.
charleneマスターズとしてログインして、解決策を見ましょう
ご覧の通り、割り当てられたロールに基づいた結果が得られます.しかし、どのようにDOS APIはどのような役割をユーザーが知っている?開発コンソールを開き、ネットワークタブを選択した場合は、サーバーにXHR要求を見てください.
見てみると、APIリクエストの一部として渡されるベアラートークンを見ることができます!
なぜなら、私たちは
pet-store-api
グループに対するクライアントの役割、これらのロールは、APIに対するベアラートークンの一部として渡されます.ガードの設定
したがって、任意の標準的なアプリケーションでは、Charleneすべての販売ビューにアクセスすることはできません.次のセクションでは、彼女の役割を確認し、SalesComponentへのアクセスを拒否するようにAuthGuardを設定します.
最初にKeyCloakを使用してルートをガードするには、AuthGuardにいくつか変更を加える必要があります.
Authガード.TS
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
@Injectable({
providedIn: 'root'
})
export class AuthGuard extends KeycloakAuthGuard {
constructor(protected router: Router, protected service: KeycloakService) {
super(router, service)
}
isAccessAllowed(route: ActivatedRouteSnapshot,state: RouterStateSnapshot) : Promise<boolean> {
return new Promise((resolve, reject) => {
resolve(true)
});
}
}
ここでは、KeyCloakラッパーを使用して、KeyCloakサーバへの正しい認証コールを確実にします.
このクラスで重要なのはisAccessAllowed()
メソッド.これは、ユーザーがコンポーネントをアクティブにすることができる場合に指示するエントリポイントです.
パスのチェックを行い、販売データにアクセスするかどうかを確認します.
Authガード.TS
isAccessAllowed(route: ActivatedRouteSnapshot,state: RouterStateSnapshot) : Promise<boolean> {
return new Promise((resolve, reject) => {
const userRoles: string[] = this.service.getUserRoles();
console.log(`Roles: ${userRoles}`);
if (state.url === '/sales' && userRoles.indexOf('employee') >= 0) {
console.log('Permission allowed');
resolve(true)
} else {
console.log('Permission not allowed');
resolve(false);
}
});
このガードの設定app-routing.module.ts
以下のように簡単です.
const routes: Routes = [
{ path: 'pets', component: PetComponent },
{ path: 'rewards', component: RewardsComponent },
{ path: 'sales', component: SalesComponent, canActivate: [AuthGuard] }
];
今すぐアクセスする場合sales.component
あなたがメッセージを見ることができるはずですPermission not allowed
コンソールでは、コンポーネントはアクティブになりません.
ノート
あなたは、我々がユーザーが持っている役割を印刷しているのを見ることができます
次のロールがあります.api-customer,customer,manage-account,manage-account-links,view-profile,offline_access,uma_authorization
それで、我々は現在我々のユーザーインターフェースと我々のバックエンドサービスを確保することができました.もちろん、より多くのあなたがこれを行うことができますが、それはあなたの安全なApplcationsにヘッドスタートを与える必要があります.
パート3では、RewardsComponentを配線し、ユーザ固有の情報をロードします!
Reference
この問題について(KeyCloak PT 2による角度とクォークの固定), 我々は、より多くの情報をここで見つけました
https://dev.to/anthonyikeda/securing-angular-and-quarkus-with-keycloak-pt-2-43bh
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
@Injectable({
providedIn: 'root'
})
export class AuthGuard extends KeycloakAuthGuard {
constructor(protected router: Router, protected service: KeycloakService) {
super(router, service)
}
isAccessAllowed(route: ActivatedRouteSnapshot,state: RouterStateSnapshot) : Promise<boolean> {
return new Promise((resolve, reject) => {
resolve(true)
});
}
}
isAccessAllowed(route: ActivatedRouteSnapshot,state: RouterStateSnapshot) : Promise<boolean> {
return new Promise((resolve, reject) => {
const userRoles: string[] = this.service.getUserRoles();
console.log(`Roles: ${userRoles}`);
if (state.url === '/sales' && userRoles.indexOf('employee') >= 0) {
console.log('Permission allowed');
resolve(true)
} else {
console.log('Permission not allowed');
resolve(false);
}
});
const routes: Routes = [
{ path: 'pets', component: PetComponent },
{ path: 'rewards', component: RewardsComponent },
{ path: 'sales', component: SalesComponent, canActivate: [AuthGuard] }
];
Reference
この問題について(KeyCloak PT 2による角度とクォークの固定), 我々は、より多くの情報をここで見つけました https://dev.to/anthonyikeda/securing-angular-and-quarkus-with-keycloak-pt-2-43bhテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol