【问题标题】:How to bypass spring security on an authenticated endpoint for specific domain?如何绕过特定域的经过身份验证的端点上的弹簧安全性?
【发布时间】:2021-09-07 12:47:14
【问题描述】:

我正在使用基于 jwt 令牌的 Spring Security。 我有一个需要身份验证的端点“/sample-endpoint”。但是,当请求来自名为 xyz.com 的特定域时,我需要绕过此端点的安全性。

可以这样做吗?如果是这样,该怎么做?

这是我目前所拥有的。

安全配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

// cant add the end point here as it would open up for everybody.
public static final String[] unauthedUrls = { "healthcheck","some-other-endpoint"}  

@Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http
                .httpBasic()
                .disable()
                .csrf()
                .disable()
                .cors()
                .and()
                .headers().frameOptions()
                .disable()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and()
                .addFilterAfter(jwtSecurityFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers(unauthedUrls)
                .permitAll()
                .anyRequest()
                .authenticated();
    }

这里是 JwtSecurityFilter 的实现。

public class JwtSecurityFilter extends OncePerRequestFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(JwtSecurityFilter.class);

    private static final String JWT_PREFIX = "Bearer ";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        setAuthenticationContext(request);

        chain.doFilter(request, response);
    }

    private void setAuthenticationContext(HttpServletRequest request) {
        try {
            String token = getJwt(request);

            if (StringUtils.isBlank(token)) {
                throw new RuntimeException("Authorization token not provided");
            }

 

// some logic here...
        } catch (Exception ex) {
      
            if (request != null && Arrays.stream(SecurityConfig.unauthedUrls).anyMatch(url -> request.getRequestURI().contains(url))) {
                // it's a URL that isn't authenticated so an exception here is normal
                // if we couldn't get a token
                return;
            }
            LOGGER.warn("Unable to authenticate request: {} {}", ex.getMessage(), request == null ? null : request.getRequestURI());
        }
    }

    private String getJwt(HttpServletRequest request) {

        String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);

        if (StringUtils.isBlank(authHeader) || !authHeader.startsWith(JWT_PREFIX)) {
            return "";
        }

        return authHeader.replaceFirst(Pattern.quote(JWT_PREFIX), "");
    }
}


【问题讨论】:

  • 欢迎来到 SO。也许您可以创建一个自定义表达式处理程序来检查 HttpServletRequest。类似.expressionHandler(new CustomDomainCheckExpressionHandler()).anyRequest().access("isDomainWhitelisted()")

标签: java spring spring-boot spring-security jwt


【解决方案1】:

您想要忽略某些 URL,因为它会覆盖接受 WebSecurity 对象并忽略模式的配置方法。比如使用api:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/api/v1/signup");
}

并从 HttpSecurity 部分中删除该行。这将告诉 Spring Security 忽略此 URL,并且不对它们应用任何过滤器。

我有更好的办法:

http
    .authorizeRequests()
    .antMatchers("/api/v1/signup/**").permitAll()
    .anyRequest().authenticated()

【讨论】:

  • 这将为所有人打开这个端点。我想保持该端点对所有人关闭,而只对特定域开放。
  • 另外,请不要复制粘贴其他帖子的答案。 stackoverflow.com/questions/30366405/…
  • @troy 欢迎来到 SO。查看内置表达式,例如hasIpAddress。见Web Security Expressions。我们需要这样的东西来检查请求域/主机。
猜你喜欢
  • 1970-01-01
  • 2012-02-15
  • 2015-09-04
  • 2015-03-19
  • 2019-07-09
  • 2021-06-05
  • 2017-09-22
  • 2010-10-21
  • 2014-05-20
相关资源
最近更新 更多