我正在尝试通过JWT获得春季安全性以与应用程序一起使用。我已经阅读了许多教程和示例,但是没有什么适合我的用例。我们不通过用户名/密码进行授权,我们使用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)
}
}
}
似乎过滤器随时会被命中,而不管其上方的许可情况如何。 不应在任何api / v1 / auth /路径上忽略过滤器吗?我想我错过了一些东西。
第二个问题,有没有一种方法可以应用此过滤器,而不必在之前或之后添加且不扩展https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html
编辑:antPathRequestMatcher并未针对configure触发,但是我什至添加了Websecurity configure的路径,我得到了该日志记录
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```
答案 0 :(得分:4)
在您的配置中,您具有:
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)
}
我看到以下内容:
.antMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated()
因此spring security正在检查所有请求的身份验证。 在我的春季配置中,我通常这样做:
.antMatchers("/swagger-ui.html","/webjars/**","/swagger-resources/**", "/v2/**","/csrf")
.permitAll()
.antMatchers("/**")
.authenticated()
因此,请尝试通过设置来更改您的配置:
override fun configure(http: HttpSecurity) {
http.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v1/auth/**").permitAll()
.antMatchers("/**").authenticated()
.and()
.addFilterBefore(JwtFilter(), UsernamePasswordAuthenticationFilter::class.java)
}
关于第二个问题:
第二个问题,有没有一种方法可以应用此过滤器而不必 在之前或之后添加且不扩展 https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html
坦白地说,在这种情况下,我将通过使用spring security和spring security oauth sprign security jwt继续使用OAuth / OpenID。
在这种情况下,我将创建一个ResourceServer配置类和一个AuthorizationServer配置类(或者可以将同一类用作AuthorizationServer和ResourceServer)。一个很好的例子在这里https://www.baeldung.com/spring-security-oauth-jwt
我希望它有用
天使
答案 1 :(得分:4)
您可以使用configure(web: WebSecurity)
,它将绕过spring安全过滤器,并且可以公开访问端点。
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/api/v1/auth/**",
"/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
您可以使用configure(http: HttpSecurity)
进行会话管理和基于角色的身份验证。您可能会看到HttpSecurity vs WebSecurity。
对于具有@Component
(或任何@Bean风格)的自定义过滤器,WebSecurityConfigurerAdapter
会告诉Spring Security忽略通过它添加的任何过滤器。然后,过滤器仍然被调用,因为@Component
(或任何形式的@Bean)注释告诉Spring将过滤器(再次)添加到安全链之外。因此,尽管在安全链中忽略了过滤器,但另一个(非安全性?)链并未忽略它。 (See Here)
答案 2 :(得分:0)
工作示例
@EnableWebSecurity
class SecurityConfig() : WebSecurityConfigurerAdapter() {
@Autowired
lateinit var tokenService: TokenService
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**","/api/v1/auth/**");
}
override fun configure(http: HttpSecurity) {
http.cors().and().csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(JwtFilter(tokenService), UsernamePasswordAuthenticationFilter::class.java)
}
}