【发布时间】:2020-04-19 11:00:45
【问题描述】:
我正在尝试通过 JWT 获得 Spring Security 以使用应用程序。我已经阅读了许多教程和示例,但没有什么真正适合我的用例。我们不通过用户名/密码进行授权,我们使用 twilio 来验证手机号码,然后我想创建一个简单的 JWT 令牌,给定一个手机号码作为主题。我已经能够做到这一点
这是一个简单的端点,存在于 /api/v1/jwt
@GetMapping("/jwt")
fun jwt(@RequestParam(value = "number", required = true) number: String): String? {
val jwtToken = Jwts.builder().setSubject(number).claim("roles", "user").setIssuedAt(Date()).signWith(SignatureAlgorithm.HS256, Base64.getEncoder().encodeToString("secret".toByteArray())).compact()
return jwtToken
}
返回一个有效的 JWT 令牌。
我的安全配置不再起作用,现在所有端点似乎都受到保护,
@Configuration
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
@Bean
override fun authenticationManagerBean(): AuthenticationManager {
return super.authenticationManagerBean()
}
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
override fun configure(http: HttpSecurity) {
http.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(JwtFilter(), UsernamePasswordAuthenticationFilter::class.java)
}
}
JWT 过滤器
@Throws(IOException::class, ServletException::class)
override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) {
val request = req as HttpServletRequest
val response = res as HttpServletResponse
val authHeader = request.getHeader("authorization")
if ("OPTIONS" == request.method) {
response.status = HttpServletResponse.SC_OK
chain.doFilter(req, res)
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw ServletException("Missing or invalid Authorization header")
}
val token = authHeader.substring(7)
try {
val claims = Jwts.parser().setSigningKey(Base64.getEncoder().encodeToString("secret".toByteArray())).parseClaimsJws(token).body
request.setAttribute("claims", claims)
} catch (e: SignatureException) {
throw ServletException("Invalid token")
}
chain.doFilter(req, res)
}
}
}
似乎过滤器随时都会被击中,不管它上面的 permitall 是什么。 过滤器不应该在任何 api/v1/auth/ 路径上被忽略吗?我想我错过了什么。
第二个问题是有没有一种方法可以应用这个过滤器而不必在之前或之后添加并且不扩展https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html
编辑:antPathRequestMatcher 没有触发配置,但我什至添加了 websecurity 配置的路径,我得到了这个日志
2019-12-30 14:44:44.792 DEBUG 81181 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /api/v1/auth/request?number=5555555 has an empty filter list```
【问题讨论】:
-
如果不被允许,您的路径不正确。为 Spring Security 启用日志记录,它会在请求该端点时准确显示匹配的路径。对于您的第二个问题,不,这是不可能的,有不同的选择,但您必须以相同的方式将它们插入安全链。
-
看起来它并没有试图查看来自 httpSecurity only webSecurity 的任何匹配器。我一定是建错了??
-
获取这些日志太疯狂了
2019-12-30 14:44:44.792 DEBUG 81181 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/v1/auth/request'; against '/api/v1/auth/request' 2019-12-30 14:44:44.792 DEBUG 81181 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /api/v1/auth/request?number=5555555555 has an empty filter list -
您的规则说允许“/api/v1/auth/**”之后的所有内容,并且任何其他请求都需要身份验证,因为您说您的 JWT 端点是“/api/v1/jwt” ",这意味着您的 JWT 端点也需要身份验证。 “/api/v1/auth/request”不受保护,或任何在“auth/**”之后的内容。
-
控制器被映射为``` @RestController @RequestMapping("/api/v1/auth") class AuthController : MainController() {}``` 所以完整路径是 api/v1/ auth/jwt 所以它不应该命中过滤器
标签: spring spring-boot spring-security jwt