Spring Security Jwt 令牌在请求表单角度时允许所有选项方法

Posted

技术标签:

【中文标题】Spring Security Jwt 令牌在请求表单角度时允许所有选项方法【英文标题】:Spring Security Jwt Token Allow all Options method while requesting form angular 【发布时间】:2019-07-20 20:54:25 【问题描述】:

不知道怎么回事,网上到处查了一下,好像和我的一样,但是遇到了这个问题:

我正在使用带有 Angular 拦截器的 HttpClient 请求我的 Angular 应用程序来 setHeader,因为我的 Java Rest API 正在使用 JWT 进行身份验证,并且在标头中需要一个令牌,因此它将获取并验证用户请求,因为 Angular 拦截器不工作适当地。我在 Java 端获取 null 作为令牌并出现错误。请帮我解决这个问题。

最后我发现它可能是弹簧安全问题,因为我调试并发现选项请求所有过滤器并且它没有标头,因此它显示令牌并抛出异常 如果选项方法请求绕过并允许那么可能是我的问题将解决

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 控制台错误

【问题讨论】:

令牌在本地存储中是否正确可用? 你在哪里注册 JwtInterceptor?它应该在 app.module.ts 中注册。也将主模块定义添加到您的问题中。你有cors的问题,也许你应该先处理它? @KrzysztofRaciniewski 可能是你问这个问题----- 提供者:[ServiceService,提供:HTTP_INTERCEPTORS,useClass:JwtInterceptor,多:真], 您在问题中分享的网络截图显示您的方法是OPTION。关于OPTION 方法,请访问此link,但根据您的控制台,您需要先解决cors 问题。 对于 cors 问题,尝试使用 http.cors 而不是 @CrossOrigin(origins = "*")。确保使用开发人员工具网络设置您的授权。不记名和令牌在您的屏幕截图中不可见。而且我还看到您使用密钥“令牌”在本地存储中获取令牌,但密钥“当前用户”在本地存储中。并且将您的 authenticationFilter 实现也可能有所帮助! 【参考方案1】:

Angular 拦截器看起来不错,但在您的浏览器控制台中有 CORS policy 错误。您的 Angular 应用在​​端口 4200 上运行,而您的后端在 8095(不同主机)上运行。

我不知道spring-boot,但是在查看文档后,您应该在后端应用程序中添加一些 cors 策略(生产和开发环境不同):

您可以在这里阅读更多内容:https://spring.io/guides/gs/rest-service-cors/

现在您对/allUser 的请求未发送...在消除 CORS 问题后,一切都应该正常工作

【讨论】:

我已经申请 @CrossOrigin(origins = "*") @RestController 你做错了什么。也许读到这个:spring.io/blog/2015/06/08/cors-support-in-spring-framework 你应该能够向不安全的控制器/方法(没有 JWT 令牌)发送请求,后端应用程序应该返回代码 200 的响应 - 这是你的优先事项,然后处理 JWT 授权 如果你喜欢我可以分享我的屏幕你可以查看 如果我允许这个 url 与令牌检查一起使用,那么我会给我适当的响应,因为它没有使用拦截器添加令牌,所以我没有在另一边得到令牌 我仍然无法解决你能帮我吗

以上是关于Spring Security Jwt 令牌在请求表单角度时允许所有选项方法的主要内容,如果未能解决你的问题,请参考以下文章

微服务 Spring Cloud Gateway + Spring Security LDAP 作为 SSO + JWT - 请求/响应之间丢失令牌

使用 Spring Security OAuth2 进行访问令牌请求的 JWT 不记名交换

如何使用 ReactJs 将 jwt 令牌提交给 Spring Security?

Spring Security + JWT学习

Spring Security JWT - 400 错误请求:“无效授权”“错误凭据”

Spring Security Jwt Token在请求表单角度时允许所有Options方法