Spring引导安全配置忽略允许的端点

Bri*_*ian 5 spring spring-security jwt spring-boot

我正在尝试使用 JWT 获得 spring 安全性以使用应用程序。我已经阅读了许多教程和示例,但没有一个真正适合我的用例。我们不通过用户名/密码授权,我们使用 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

    }
Run Code Online (Sandbox Code Playgroud)

它返回一个有效的 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎过滤器随时都会被击中,无论它上面的许可如何。过滤器不应该在任何 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```
Run Code Online (Sandbox Code Playgroud)

Ang*_*ata 5

在您的配置中,您有:

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)
}
Run Code Online (Sandbox Code Playgroud)

我看到以下内容:

.antMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated()
Run Code Online (Sandbox Code Playgroud)

因此 Spring Security 正在检查所有请求的身份验证。在我的 spring 配置中,我通常这样做:

.antMatchers("/swagger-ui.html","/webjars/**","/swagger-resources/**", "/v2/**","/csrf")
.permitAll()
.antMatchers("/**")
.authenticated()
Run Code Online (Sandbox Code Playgroud)

因此,尝试通过设置更改您的配置:

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)
}
Run Code Online (Sandbox Code Playgroud)

关于你的第二个问题:

第二个问题是有一种方法可以应用此过滤器,而不必在之前或之后添加并且不扩展 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

我希望它有用

安吉洛


Pat*_*mil 4

您可以使用configure(web: WebSecurity),这将绕过 Spring Security 过滤器,并且可以公开访问端点。

override fun configure(web: WebSecurity) {
        web.ignoring().antMatchers("/api/v1/auth/**",
                "/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }
Run Code Online (Sandbox Code Playgroud)

您可以用于configure(http: HttpSecurity)会话管理和基于角色的身份验证。您可能会看到HttpSecurity 与 WebSecurity

对于具有@Component(或任何@Bean风格)的自定义过滤器,WebSecurityConfigurerAdapter将告诉Spring Security忽略通过它添加的任何过滤器。然后过滤器仍然被调用,因为@Component(或 @Bean 的任何风格)注释告诉 Spring 将过滤器(再次)添加到安全链之外。因此,虽然过滤器在安全链中被忽略,但它并没有被其他(非安全?)链忽略。(看这里