احراز هویت و اعتبارسنجی کاربران در برنامههای Angular - قسمت ششم - کار با منابع محافظت شدهی سمت سرور
نویسنده: وحید نصیری
تاریخ: ۱۳۹۶/۰۹/۳۰ ۸:۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
>ng g c Dashboard/CallProtectedApi
import { CallProtectedApiComponent } from "./call-protected-api/call-protected-api.component";
const routes: Routes = [
{
path: "callProtectedApi",
component: CallProtectedApiComponent,
data: {
permission: {
permittedRoles: ["Admin", "User"],
deniedRoles: null
} as AuthGuardPermission
},
canActivate: [AuthGuard]
}
]; <li *ngIf="isLoggedIn" routerLinkActive="active">
<a [routerLink]="['/callProtectedApi']">Call Protected Api</a>
</li> import { Component, OnInit } from "@angular/core";
import { AuthService } from "../../core/services/auth.service";
@Component({
selector: "app-call-protected-api",
templateUrl: "./call-protected-api.component.html",
styleUrls: ["./call-protected-api.component.css"]
})
export class CallProtectedApiComponent implements OnInit {
isAdmin = false;
isUser = false;
result: any;
constructor(private authService: AuthService) { }
ngOnInit() {
this.isAdmin = this.authService.isAuthUserInRole("Admin");
this.isUser = this.authService.isAuthUserInRole("User");
}
callMyProtectedAdminApiController() {
}
callMyProtectedApiController() {
}
} <button *ngIf="isAdmin" (click)="callMyProtectedAdminApiController()">
Call Protected Admin API [Authorize(Roles = "Admin")]
</button>
<button *ngIf="isAdmin || isUser" (click)="callMyProtectedApiController()">
Call Protected API ([Authorize])
</button>
<div *ngIf="result">
<pre>{{result | json}}</pre>
</div> getBearerAuthHeader(): HttpHeaders {
return new HttpHeaders({
"Content-Type": "application/json",
"Authorization": `Bearer ${this.getRawAuthToken(AuthTokenType.AccessToken)}`
});
} import { Injectable } from "@angular/core";
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import { AuthService, AuthTokenType } from "./auth.service";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const accessToken = this.authService.getRawAuthToken(AuthTokenType.AccessToken);
if (accessToken) {
request = request.clone({
headers: request.headers.set("Authorization", `Bearer ${accessToken}`)
});
}
return next.handle(request);
}
} import { HTTP_INTERCEPTORS } from "@angular/common/http";
import { AuthInterceptor } from "./services/auth.interceptor";
@NgModule({
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
]
})
export class CoreModule {} compiler.js:19514 Uncaught Error: Provider parse errors:
Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1 import { Injector } from "@angular/core";
constructor(private injector: Injector) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService); @Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private injector: Injector) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService);
const accessToken = authService.getRawAuthToken(AuthTokenType.AccessToken);
if (accessToken) {
request = request.clone({
headers: request.headers.set("Authorization", `Bearer ${accessToken}`)
});
}
return next.handle(request);
}
} constructor(
private authService: AuthService,
private httpClient: HttpClient,
@Inject(APP_CONFIG) private appConfig: IAppConfig,
) { } callMyProtectedAdminApiController() {
this.httpClient
.get(`${this.appConfig.apiEndpoint}/MyProtectedAdminApi`)
.map(response => response || {})
.catch((error: HttpErrorResponse) => Observable.throw(error))
.subscribe(result => {
this.result = result;
});
}
callMyProtectedApiController() {
this.httpClient
.get(`${this.appConfig.apiEndpoint}/MyProtectedApi`)
.map(response => response || {})
.catch((error: HttpErrorResponse) => Observable.throw(error))
.subscribe(result => {
this.result = result;
});
}
return next.handle(request)
.catch((error: any, caught: Observable<HttpEvent<any>>) => {
if (error.status === 401 || error.status === 403) {
this.router.navigate(["/accessDenied"]);
}
return Observable.throw(error);
}); @Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private injector: Injector,
private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService);
const accessToken = authService.getRawAuthToken(AuthTokenType.AccessToken);
if (accessToken) {
request = request.clone({
headers: request.headers.set("Authorization", `Bearer ${accessToken}`)
});
return next.handle(request)
.catch((error: any, caught: Observable<HttpEvent<any>>) => {
if (error.status === 401 || error.status === 403) {
this.router.navigate(["/accessDenied"]);
}
return Observable.throw(error);
});
} else {
// login page
return next.handle(request);
}
}
} using ASPNETCore2JwtAuthentication.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace ASPNETCore2JwtAuthentication.WebApp.Controllers
{
[Route("api/[controller]")]
[EnableCors("CorsPolicy")]
[Authorize(Policy = CustomRoles.Editor)]
public class MyProtectedEditorsApiController : Controller
{
public IActionResult Get()
{
return Ok(new
{
Id = 1,
Title = "Hello from My Protected Editors Controller! [Authorize(Policy = CustomRoles.Editor)]",
Username = this.User.Identity.Name
});
}
}
} callMyProtectedEditorsApiController() {
this.httpClient
.get(`${this.appConfig.apiEndpoint}/MyProtectedEditorsApi`)
.map(response => response || {})
.catch((error: HttpErrorResponse) => Observable.throw(error))
.subscribe(result => {
this.result = result;
});
}
ngOnInit() {
this.isAdmin = this.authService.isAuthUserInRole("Admin");
this.isUser = this.authService.isAuthUserInRole("User");
} import { Directive, ElementRef, Input, OnDestroy, OnInit } from "@angular/core";
import { Subscription } from "rxjs/Subscription";
import { AuthService } from "../../core/services/auth.service";
@Directive({
selector: "[isVisibleForAuthUser]"
})
export class IsVisibleForAuthUserDirective implements OnInit, OnDestroy {
private subscription: Subscription;
@Input() isVisibleForRoles: string[];
constructor(private elem: ElementRef, private authService: AuthService) { }
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
ngOnInit(): void {
this.subscription = this.authService.authStatus$.subscribe(status => this.changeVisibility(status));
this.changeVisibility(this.authService.isAuthUserLoggedIn());
}
private changeVisibility(status: boolean) {
const isInRoles = !this.isVisibleForRoles ? true : this.authService.isAuthUserInRoles(this.isVisibleForRoles);
this.elem.nativeElement.style.display = isInRoles && status ? "" : "none";
}
} import { IsVisibleForAuthUserDirective } from "./directives/is-visible-for-auth-user.directive";
@NgModule({
declarations: [
IsVisibleForAuthUserDirective
],
exports: [
IsVisibleForAuthUserDirective
]
})
export class SharedModule {} import { SharedModule } from "../shared/shared.module";
@NgModule({
imports: [
SharedModule
]
})
export class DashboardModule { } <div class="alert alert-info" isVisibleForAuthUser>
Is-Visible-For-AuthUser
</div> <div class="alert alert-success" isVisibleForAuthUser [isVisibleForRoles]="['Admin','User']">
Is-Visible-For-Roles = ['Admin','User']
</div> @Directive({
selector: "[isVisibleForAuthUser]"
})
export class IsVisibleForAuthUserDirective implements OnInit, OnDestroy {
constructor(private elem: ElementRef, private authService: AuthService) { } @Directive({
selector: "[hasAuthUserViewPermission]"
})
export class HasAuthUserViewPermissionDirective implements OnInit, OnDestroy {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private authService: AuthService
) { } <div *hasAuthUserViewPermission="['Admin','User']">
*hasAuthUserViewPermission="['Admin','User']"
</div> this.viewContainer.createEmbeddedView(this.templateRef);
this.viewContainer.clear();
import { Directive, Input, OnDestroy, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
import { Subscription } from "rxjs/Subscription";
import { AuthService } from "./../../core/services/auth.service";
@Directive({
selector: "[hasAuthUserViewPermission]"
})
export class HasAuthUserViewPermissionDirective implements OnInit, OnDestroy {
private isVisible = false;
private requiredRoles: string[] | null = null;
private subscription: Subscription | null = null;
@Input()
set hasAuthUserViewPermission(roles: string[] | null) {
this.requiredRoles = roles;
}
// Note, if you don't place the * in front, you won't be able to inject the TemplateRef<any> or ViewContainerRef into your directive.
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private authService: AuthService
) { }
ngOnInit() {
this.subscription = this.authService.authStatus$.subscribe(status => this.changeVisibility(status));
this.changeVisibility(this.authService.isAuthUserLoggedIn());
}
ngOnDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
private changeVisibility(status: boolean) {
const isInRoles = !this.requiredRoles ? true : this.authService.isAuthUserInRoles(this.requiredRoles);
if (isInRoles && status) {
if (!this.isVisible) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.isVisible = true;
}
} else {
this.isVisible = false;
this.viewContainer.clear();
}
}
} import { HasAuthUserViewPermissionDirective } from "./directives/has-auth-user-view-permission.directive";
@NgModule({
declarations: [
HasAuthUserViewPermissionDirective
],
exports: [
HasAuthUserViewPermissionDirective
]
})
export class SharedModule {} import { SharedModule } from "../shared/shared.module";
@NgModule({
imports: [
SharedModule
]
})
export class DashboardModule { } <div *hasAuthUserViewPermission="">
*hasAuthUserViewPermission=""
</div> <div *hasAuthUserViewPermission="['Admin','User']">
*hasAuthUserViewPermission="['Admin','User']"
</div> this.authStatusSource.next(true);
this.authService.authStatus$.subscribe(status => this.changeVisibility(status));
Request URL: http://localhost:5000/api/office?page=1&pageSize=5
Request Method: GET Status Code: 401 Unauthorized Remote Address: [::1]:5000 Referrer Policy: no-referrer-when-downgrade
Request URL: http://localhost:5000/api/ChangePassword Request Method: POST Status Code: 400 Bad Request Remote Address: [::1]:5000 Referrer Policy: no-referrer-when-downgrade