Spring Boot 自定义 JWT 过滤器不允许任何没有令牌的请求
Posted
技术标签:
【中文标题】Spring Boot 自定义 JWT 过滤器不允许任何没有令牌的请求【英文标题】:Spring boot custom JWT filter not allowing any request without token 【发布时间】:2021-03-30 23:54:46 【问题描述】:我正在使用带有 Spring Boot 安全配置的自定义 JWT 过滤器来允许某些没有 JWT 令牌的 API 请求。但是 WebSecurity 配置中的 permitAll() 方法不起作用(不允许任何没有 JWT 的请求)。它会引发自定义 InvalidJwtException。我在这里缺少什么?我已经尝试了很多谷歌搜索,但没有成功。
WebSecurityConfig 类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfig(
private val jwtTokenProvider: JwtTokenProvider,
private val filterChainExceptionHandler: FilterChainExceptionHandler,
) : WebSecurityConfigurerAdapter()
override fun configure(http: HttpSecurity?)
http?.csrf()?.disable()
http?.sessionManagement()?.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
http
?.authorizeRequests()
?.antMatchers("/api/v1/auth/signin")?.permitAll()
?.antMatchers("/api/v1/auth/checkEmailExist")?.permitAll()
?.anyRequest()?.authenticated()
http
?.addFilterBefore(JwtTokenFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter::class.java)
?.addFilterBefore(filterChainExceptionHandler, JwtTokenFilter::class.java)
@Bean
fun passwordEncoder(): PasswordEncoder
return BCryptPasswordEncoder(10)
@Bean
override fun authenticationManagerBean(): AuthenticationManager
return super.authenticationManagerBean()
JwtTokenFilter 类
@Component
class JwtTokenFilter(
private val jwtTokenProvider: JwtTokenProvider
) : OncePerRequestFilter()
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
)
try
val token = jwtTokenProvider.resolveToken(request)
if (token != null && jwtTokenProvider.validateToken(token))
val auth = jwtTokenProvider.getAuthentication(token)
SecurityContextHolder.getContext().authentication = auth
catch (e: InvalidJwtException)
SecurityContextHolder.clearContext()
throw InvalidJwtException(e.message, e.httpStatus)
filterChain.doFilter(request, response)
解析令牌函数
fun resolveToken(req: HttpServletRequest): String?
val bearerToken = req.getHeader(AUTHORIZATION_HEADER)
return if (bearerToken != null && bearerToken.startsWith(BEARER))
bearerToken.substring(7)
else
throw InvalidJwtException("Authorization token must be Bearer [token]", HttpStatus.FORBIDDEN)
【问题讨论】:
那是你自己的代码在做的事情,没有token的时候,抛出异常。因为这总是在任何规则检查之前执行,所以它总是会抛出这个异常。因此不要抛出异常。 这行不应该允许没有令牌的两个请求吗?因为它有 permitAll ()antMatchers("/api/v1/auth/signin")?.permitAll() antMatchers("/api/v1/auth/checkEmailExist")?.permitAll() 没有。无论它是谁,它总是可以访问。但是,确定谁需要身份验证并在评估permitAll
之前调用。如果您想禁用所有过滤器(不推荐),请将网络安全配置为 ignore
某些 URL然而,这会禁用该 URL 的所有安全过滤器。
【参考方案1】:
您的令牌验证应排除身份验证 URL:
if (!request.getRequestURL().toString().contains("auth") || (token != null && jwtTokenProvider.validateToken(token)))
您可以选择比我使用过的“auth”更好的字符串来识别排除的路径
【讨论】:
以上是关于Spring Boot 自定义 JWT 过滤器不允许任何没有令牌的请求的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Apache Shrio + JWT前后端分离项目
Spring boot + JWT 实现安全验证 ---auth0.jwt
添加自定义过滤器 Apache Shiro + Spring Boot