gpt4 book ai didi

java - 带有 permitAll() 和过期 Auth Token 的 URL 的 Spring Security

转载 作者:搜寻专家 更新时间:2023-11-01 01:07:46 25 4
gpt4 key购买 nike

我将 Spring 4 与 Spring Security、自定义 GenericFilterBean 和 AuthenticationProvider 实现结合使用。除了用于创建新 session 的 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 在每个请求上运行并从请求 header 获取 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 将尝试根据 header 中提供的 token 对所有请求进行身份验证,如果身份验证不成功 - 抛出 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());
}
}

这对于需要身份验证的请求非常有效。这适用于没有身份验证 header 的 /v2/session 请求。但是,对于 header 中(或 cookie 中没有显示在代码示例中)具有过期身份验证 token 的 /v2/session 请求;如果客户端未清除 header 或继续发送带有请求的 cookie)安全上下文将被初始化并且 apiAuthenticationProvider 将抛出异常并使用 HTTP 401 响应客户端。

由于 /v2/session 已配置为

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

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

最佳答案

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

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

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

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

这样做是为了 POST/v2/sessions URL 完全绕过您的 AuthTokenHeaderAuthenticationFilter

关于java - 带有 permitAll() 和过期 Auth Token 的 URL 的 Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29503952/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com