使用过滤器实现基于JWT的Spring Security时,我们可能会遇到403错误而不是预期的401错误。本文将介绍如何解决这个问题,并提供相关的案例代码。
在使用Spring Boot 2构建基于JWT的Spring Security时,我们通常会使用过滤器来验证和处理JWT。JWT(JSON Web Token)是一种用于身份验证和授权的安全传输方式。在Spring Security中,我们可以使用过滤器来拦截请求,并对JWT进行校验和解析。然而,有时候我们可能会发现,当JWT无效或过期时,我们期望返回401错误(未授权),但实际上却返回了403错误(禁止访问)。这是因为Spring Security默认情况下,会对所有请求进行授权检查,包括那些未经身份验证的请求。为了解决这个问题,我们需要对Spring Security的授权过滤器进行配置,以便在JWT无效或过期时返回401错误。配置Spring Security首先,我们需要创建一个自定义的过滤器,用于验证和解析JWT。这个过滤器需要继承自`OncePerRequestFilter`类,并重写`doFilterInternal`方法。javapublic class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 验证和解析JWT // ... filterChain.doFilter(request, response); }}接下来,我们需要配置Spring Security,将这个自定义的过滤器添加到过滤器链中,并设置相应的授权策略。
java@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtAuthenticationFilter jwtAuthenticationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/public").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) .exceptionHandling() .authenticationEntryPoint((request, response, authenticationException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized")); }}在上面的配置中,我们使用`jwtAuthenticationFilter`作为授权过滤器,并将其添加到`UsernamePasswordAuthenticationFilter`之前。同时,我们还设置了一个自定义的`authenticationEntryPoint`,用于处理未授权的请求,并返回401错误。测试现在,我们可以进行一些测试来验证我们的配置是否生效。假设我们有一个公开的API `/api/public`,不需要身份验证。而其它所有的API都需要进行身份验证。当我们使用有效的JWT进行访问时,我们应该能够成功访问所有需要进行身份验证的API。当我们使用无效或过期的JWT进行访问时,我们应该收到401错误(未授权)。
java@RestControllerpublic class ApiController { @GetMapping("/api/public") public ResponseEntity在上面的代码中,`/api/public`是一个公开的API,不需要身份验证。而`/api/private`是一个私有的API,需要进行身份验证。通过配置Spring Security的授权过滤器,我们可以解决基于过滤器的JWT Spring Security实现中返回403而不是401的问题。通过返回401错误,我们可以更准确地表示请求未经授权,而不是仅仅禁止访问。通过本文的案例代码,我们可以清楚地了解到如何配置Spring Security和自定义过滤器来实现基于JWT的身份验证和授权。这将有助于我们构建更安全和可靠的应用程序。publicApi() { return ResponseEntity.ok("Public API"); } @GetMapping("/api/private") public ResponseEntity privateApi() { return ResponseEntity.ok("Private API"); }}