繁体   English   中英

带有permitAll()和过期身份验证令牌的URL的Spring Security

[英]Spring Security for URL with permitAll() and expired Auth Token

我正在使用带有Spring Security的Spring 4,自定义GenericFilterBean和AuthenticationProvider实现。 除了URL以创建新会话之外,我主要保护URL: / v2 / session (例如,基于用户名和密码登录,并返回Auth Token以用于后续需要身份验证的请求),配置如下:

@Configuration
@ComponentScan(basePackages={"com.api.security"})
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private ApiAuthenticationProvider apiAuthenticationProvider;

@Autowired
private AuthTokenHeaderAuthenticationFilter authTokenHeaderAuthenticationFilter;

@Autowired
private AuthenticationEntryPoint apiAuthenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(apiAuthenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(authTokenHeaderAuthenticationFilter, BasicAuthenticationFilter.class) // Main auth filter
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()
        .anyRequest().authenticated();

    http.exceptionHandling()
        .authenticationEntryPoint(apiAuthenticationEntryPoint);
}
}

authTokenHeaderAuthenticationFilter在每个请求上运行,并从请求标头获取Token:

/**
 * Main Auth Filter. Always sets Security Context if the Auth token Header is not empty
 */
@Component
public class AuthTokenHeaderAuthenticationFilter extends GenericFilterBean {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    final String token = ((HttpServletRequest) request).getHeader(RequestHeaders.AUTH_TOKEN_HEADER);
    if (StringUtils.isEmpty(token)) {
        chain.doFilter(request, response);
        return;
    }

    try {
            AuthenticationToken authRequest = new AuthenticationToken(token);

              SecurityContextHolder.getContext().setAuthentication(authRequest);
        }
    } catch (AuthenticationException failed) {
        SecurityContextHolder.clearContext();

        return;
    }

    chain.doFilter(request, response); // continue down the chain
}

}

自定义apiAuthenticationProvider将尝试根据标头中提供的令牌对所有请求进行身份验证,如果身份验证不成功,则抛出AccessException,客户端将收到HTTP 401响应:

@Component
public class ApiAuthenticationProvider implements AuthenticationProvider {

@Autowired
private remoteAuthService remoteAuthService;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    AuthenticationToken authRequest = (AuthenticationToken) authentication;
    String identity = null;

    try {
        identity = remoteAuthService.getUserIdentityFromToken(authRequest.getToken());
    } catch (AccessException e) {
        throw new InvalidAuthTokenException("Cannot get user identity from the token", e);
    }

    return new AuthenticationToken(identity, authRequest.getToken(), getGrantedAuthorites());
    }
    }

这对于需要身份验证的请求非常有效。 这适用于/ v2 /会话请求,但不包含Authentication Header。 但是,对于在标头中(或在cookie中未显示的代码示例中具有过期的Auth标记的/ v2 /会话请求;如果客户端未清除标头或继续发送带有请求的cookie,则有时会发生这种情况; )安全上下文将被初始化, apiAuthenticationProvider将抛出异常并使用HTTP 401响应客户端。

由于/ v2 / session已配置为

http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()

我希望Spring Security在调用ApiAuthenticationProvider.authenticate()之前确定它。 过滤器或身份验证提供程序应该忽略/不抛出配置为permitAll()的URL的异常的方式是什么?

在执行请求授权检查之前,会触发Spring安全筛选器。 要使授权检查起作用,假定请求已通过过滤器并且已设置Spring安全上下文(或不设置,具体取决于是否已传入身份验证凭据)。

在过滤器中,如果令牌不存在,则检查是否继续进行过滤器链处理。 不幸的是,如果是,那么它将被传递给您的提供者进行身份验证,这会引发异常,因为令牌已过期,因此您获得了401。

您最好的选择是绕过您认为公开的URL的过滤器执行。 您可以在过滤器本身或配置类中执行此操作。 将以下方法添加到SecurityConfig类:

@Override
public void configure(WebSecurity webSecurity) {
  webSecurity.ignoring().antMatchers(HttpMethod.POST, "/v2/session");
}

这将做什么,完全绕过您的AuthTokenHeaderAuthenticationFilter POST /v2/sessions URL。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM