ค้นหาเว็บไซต์

Spring Security Jwt Token อนุญาตทุกเมธอด Options ขณะส่งคำขอจาก Angular


ฉันไม่รู้ว่ามีอะไรผิดพลาด ฉันตรวจสอบทางออนไลน์ทุกที่ ดูเหมือนว่ามันจะเหมือนกับที่ฉันมี แต่ฉันกำลังเจอปัญหานี้:

ฉันกำลังร้องขอให้แอป Angular ของฉันใช้ HttpClient กับ Angular interceptor เพื่อกำหนด Header เพราะ Java Rest API ของฉันใช้ JWT สำหรับการยืนยันตัวตนและต้องการโทเค็นใน Header เพื่อที่จะดึงและตรวจสอบคำขอของผู้ใช้ แต่ Angular interceptor ไม่ทำงานอย่างถูกต้อง ฉันได้รับค่า null เป็นโทเค็นที่ฝั่ง Java และเกิดข้อผิดพลาด กรุณาช่วยฉันด้วย

สุดท้ายผมพบว่ามันอาจจะเป็นปัญหาของ Spring Security เพราะผมดีบักแล้วพบว่าการร้องขอแบบ OPTIONS ผ่านฟิลเตอร์ทั้งหมดและมันไม่ได้มี header ดังนั้นมันจึงแสดง token และโยนข้อยกเว้น หากการร้องขอแบบ OPTIONS สามารถข้ามและอนุญาตได้ ปัญหาอาจจะถูกแก้

การกำหนดค่าความปลอดภัยของ Spring Boot

package com.techprimers.security.jwtsecurity.config;

import com.techprimers.security.jwtsecurity.security.JwtAuthenticationEntryPoint;
import com.techprimers.security.jwtsecurity.security.JwtAuthenticationProvider;
import com.techprimers.security.jwtsecurity.security.JwtAuthenticationTokenFilter;
import com.techprimers.security.jwtsecurity.security.JwtSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Collections;

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private JwtAuthenticationProvider authenticationProvider;
    @Autowired
    private JwtAuthenticationEntryPoint entryPoint;

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Collections.singletonList(authenticationProvider));
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilter() {
        JwtAuthenticationTokenFilter filter = new JwtAuthenticationTokenFilter();
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(new JwtSuccessHandler());
        return filter;
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
                .authorizeRequests().antMatchers("**/rest/**").authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(entryPoint)
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        http.headers().cacheControl();



    }
}

โค้ดตัวดักจับของ Angular

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // add authorization header with jwt token if available



            console.log("i am inside");

            request = request.clone({
                setHeaders: {
                    Accept: 'application/json',
                    Authorization: `Bearer ${localStorage.getItem('token')}`
                }
            });


        return next.handle(request);
    }
}

บริการ Angular

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ServiceService {

  constructor(private http: HttpClient) { }

  api_user_url = 'http://localhost:8095';

  getAllApiUsers(): Observable<any> {
    return this.http.get(this.api_user_url + "/allUser");
  }

  setUserLogin(obj):Observable<any>{

    return this.http.post(this.api_user_url +"/login", obj);
  }
}

เรียกวิธีการ

public getAllUserList() {

    console.log("I am calling");

    this.service.getAllApiUsers()
      .subscribe(data => {
        this.alluser = data;
        console.log(data);

      })
  }

เครือข่ายเบราว์เซอร์

ที่เก็บข้อมูลภายในเครื่องสำหรับโทเค็น

ข้อความแสดงข้อผิดพลาดของคอนโซลเบราว์เซอร์

ข้อผิดพลาดคอนโซล Spring Boot Java

คำตอบ #1

ฉันคิดว่าคำตอบที่ถูกต้องสำหรับคำถามของคุณอยู่ใน JwtSecurityConfig คุณจำเป็นต้องเพิ่มการเรียก OPTIONS ให้สามารถผ่านความปลอดภัยของ JWT ได้โดยไม่ต้องขอโทเค็นการตรวจสอบสิทธิ์

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf().disable()
            .authorizeRequests()
            // Add this line to your code
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers("**/rest/**").authenticated()
            .and()
            .exceptionHandling().authenticationEntryPoint(entryPoint)
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    http.headers().cacheControl();



}

คำตอบ #2

ตัวดักจับของ Angular ดูดี แต่ในคอนโซลเบราว์เซอร์ของคุณมีข้อผิดพลาด นโยบาย CORS แอป Angular ของคุณกำลังทำงานบนพอร์ต 4200 และแบ็กเอนด์ของคุณกำลังทำงานบน 8095 (โฮสต์ต่างกัน)

ฉันไม่รู้จัก spring-boot แต่หลังจากตรวจสอบเอกสารแล้ว คุณควรเพิ่มนโยบาย CORS บนแอปพลิเคชันด้านหลัง (แตกต่างกันสำหรับสภาพแวดล้อมการผลิตและการพัฒนา):

คุณสามารถอ่านเพิ่มเติมได้ที่นี่: https://spring.io/guides/gs/rest-service-cors/

ตอนนี้คำขอของคุณไปที่ /allUser ยังไม่ได้ส่ง... หลังจากแก้ปัญหา CORS ทุกอย่างควรทำงานได้อย่างถูกต้อง