HTTP 403 Даже я вошел в систему - PullRequest
0 голосов
/ 21 марта 2020

Я пытаюсь разработать проект django / angular и использую базовую модель пользователя для django пользователя. Я пытался реализовать аутентификацию JWT в обе стороны. На django стороне я использую библиотеку rest_framework_jwt.

Я проверил поток токенов с клиентской стороны на серверную. На простой странице входа в систему на angular я использую свое имя пользователя и пароль для входа в систему. Он принимает мои данные и перенаправляет меня на главную страницу, где я использую сервис для получения «фида» данных со стороны сервера. На этом этапе это дает мне ошибку 403. Кстати, когда я использую Postman для проверки scener ios, я добавляю jwt в качестве заголовка авторизации, такого как «JWT», и он все еще дает мне «Учетные данные аутентификации не были предоставлены». Жду ваших подсказок. Спасибо.

django -> settings.py middleware;

MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

django -> settings py rest_framework;

REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATON_CLASSES':(
    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
),
'NON_FIELD_ERRORS_KEY': 'global',
}

я использую эти настройки для jwt

#JWT SETTINGS
 JWT_AUTH = {
    'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': timedelta(days=2) # datetime imported at start
}

с использованием classi c urls.py (его и включенная часть, поэтому он начинается с api / auth /)

urlpatterns = [
 path('login/', obtain_jwt_token),
 path('refresh-token/', refresh_jwt_token),
]

в начале, у меня есть перехватчик, authservice и feedservice

authservice

import { Injectable } from '@angular/core';
import { HttpClient, HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { tap, shareReplay } from 'rxjs/operators';
import * as JwtDecode from 'jwt-decode';
import * as moment from 'moment';
import { JWTPayload } from '../interfaces/JWTPayload';
// logs in and out, notifies other components with subscription
@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  URL_API = 'http://localhost:80/api/auth';


  constructor(private http: HttpClient) { }

  private setSession(authResult) {
    const token = authResult.token;
    const payload = <JWTPayload>JwtDecode(token);
    const expiresAt = moment.unix(payload.exp);

    localStorage.setItem('token', authResult.token);
    localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
  }

  get token(): string {
    return localStorage.getItem('token');
  }

  login(username: string, password: string) {
    return this.http.post(`${this.URL_API}/login/`, { username, password })
      .pipe(tap(
        response => {
          console.log("API CALL RESPONSE FOR LOGIN => ", response);
          this.setSession(response);
        }
      ),
        shareReplay(),
      );
  }

  logout() {

    localStorage.removeItem('token');
    localStorage.removeItem('expires_at');
    console.log("CIKIS YAPILDI ");
  }

  refreshToken() {
    if (moment().isBetween(this.getExpiration().subtract(1, 'days'), this.getExpiration())) {
      return this.http.post(
        `${this.URL_API}/refresh-token/`,
        { token: this.token }
      ).pipe(
        tap(response => { this.setSession(response); console.log("response for refresh token=>", response); }),
        shareReplay(),
      ).subscribe();
    }
  }

  getExpiration() {
    const expiration = localStorage.getItem('expires_at');
    const expiresAt = JSON.parse(expiration);
    console.log("expires=>", moment(expiresAt).calendar());
    return moment(expiresAt);
  }

  isLoggedIn() {
    return moment().isBefore(this.getExpiration());
  }

  isLoggedOut() {
    return !this.isLoggedIn();
  }
}

перехватчик

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthenticationService } from '../services/authentication.service';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

// intercepts every api call and adds jwt header to call.
@Injectable({
  providedIn: 'root'
})
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('token');
    console.log("firs token check => ", token);

    if (token) {
      console.log("gecerli token=> ", token)
      const cloned = req.clone({
        headers: req.headers.set('Authorization', 'JWT '.concat(token))
      });
      console.log("cloned ->", cloned.body);
      return next.handle(cloned);
    } else {
      console.log("next.handle(req) => ", next.handle(req));
      return next.handle(req);
    }
  }
}

feedservice

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from "rxjs";
import { Post } from '../interfaces/Post';
@Injectable({
  providedIn: 'root'
})
export class FeedService {
  API_URL = 'http://localhost:80'
  constructor(private httpClient: HttpClient) { }

  public getFeed(): Observable<Post[]> {
    return this.httpClient.get<Post[]>(`${this.API_URL}/api/feed/`);
  }

  public retrievePost(post_id: number): Observable<Post> {
    return this.httpClient.get<Post>(`${this.API_URL}/api/feed/${post_id}`)
  }

  public postFeed(post: Post) {
    return this.httpClient.post(`${this.API_URL}/api/feed/`, post)
  }
}

и в финале есть компонент входа

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { first } from 'rxjs/operators';

import { AuthenticationService } from '../services/authentication.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  loginForm: FormGroup
  returnUrl: string
  loading = false;
  submitted = false;
  error = '';
  constructor(
    private formBuilder: FormBuilder,
    private authenticationService: AuthenticationService,
    private router: Router,
    private route: ActivatedRoute
  ) {
    //redirect home if already logged in
    if (authenticationService.isLoggedIn()) {
      console.log("isLoggedIn() => already logged in")
      router.navigate(['/']);
    }
  }

  ngOnInit(): void {
    this.loginForm = this.formBuilder.group({
      username: ['', Validators.required],
      password: ['', Validators.required]
    });

    //get returl url  or redirect to /
    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
  }

  //easy way to access fields
  get f() { return this.loginForm.controls }

  onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.loginForm.invalid) { console.log("if code block => invalid credentials"); return; }

    this.loading = true;
    this.authenticationService.login(this.f.username.value, this.f.password.value)
      .subscribe(
        success => { console.log("succesfull login"); this.router.navigate([this.returnUrl]); },
        error => {
          this.error = error;
          this.loading = false;
          console.log("errors =>", error);
        }
      );

  }
}

1 Ответ

0 голосов
/ 22 марта 2020

Я понял это. В представлении моего другого API я добавил эти строки

permission_classes = [ IsAuthenticated ]
authentication_classes = [ JSONWebTokenAuthentication ]

, и это сработало!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...