我一直在尝试实施OAuth2密码到期过滤器,我不确定这样做的正确方法。这个想法如下:
所以......我在密码过期的用户详细信息中设置了一个自定义标志,因为我在DaoAuthenticationProvider中验证时不能使用credentialsNonExpired,并作为异常被抛出,因为InvalidGrantException没有给出我很有控制力。我已经发现,为了在身份验证后立即访问用户详细信息,我的过滤器应位于OAuth2AuthenticationProcessingFilter之后的内部Spring Security过滤器链中:
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
...
http.addFilterAfter(new PasswordExpirationFilter(), BasicAuthenticationFilter.class
}
}
如果该用户的密码已过期,我的过滤器会生成一些随机字符串,并在密码更改请求期间将其保存以检索用户详细信息(至少应该是这样):
public class PasswordExpirationFilter extends OncePerRequestFilter implements Filter, InitializingBean {
private static final String TOKEN_HEADER = ...;
private ExpiredPasswordRepository repo; // gets set in a constructor and is basically holding a concurrent map of tokens
...
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
UserDetails details = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (details.isPasswordExpired) {
String uuid = UUID.randomUUID().toString();
repo.push(uuid, details.getId());
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(null);
request.getSession(false).invalidate(); // don't create a new session
response.addHeader(TOKEN_HEADER, uuid);
response.sendError(HttpStatus.SC_PRECONDITION_FAILED, "Credentials have expired");
} else {
filterChain.doFilter(request, response);
}
}
}
我是否还必须撤销OAuth令牌?它会在以后的请求中重用,并且我不断获取最后一个userDetails对象,因此我不断从我的过滤器获得相同的响应。
答案 0 :(得分:0)
好吧,我想我通过在我的过滤器中注入TokenStore来撤销访问令牌来解决这个问题(我使用BearerTokenExtractor来获取令牌值),这在这个看起来很合乎逻辑。我仍然没有时间弄明白,为什么我的过滤器会在OAuth2AuthenticationProcessingFilter之后放置。