如何绕过特定域的经过身份验证的端点上的弹簧安全性?
Posted
技术标签:
【中文标题】如何绕过特定域的经过身份验证的端点上的弹簧安全性?【英文标题】: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()")
【参考方案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()
【讨论】:
这将为所有人打开这个端点。我想保持该端点对所有人关闭,而只对特定域开放。 另外,请不要复制粘贴其他帖子的答案。 ***.com/questions/30366405/… @troy 欢迎来到 SO。查看内置表达式,例如hasIpAddress
。见Web Security Expressions。我们需要这样的东西来检查请求域/主机。以上是关于如何绕过特定域的经过身份验证的端点上的弹簧安全性?的主要内容,如果未能解决你的问题,请参考以下文章