我们正在使用 spring security OAuth2 保护 REST 服务。应用程序可以调用 /oauth/authorize
, /oauth/token
或 /rest-api
端点。 token 和 rest-api 端点是无状态的,不需要 session 。
我们可以在用户通过身份验证后使 session 无效吗?如果是这样,最好的方法是什么。我们希望用户在调用 /oauth/authorize
时始终登录制作。目前,调用/oauth/authorize
只要 session 存在,就会跳过身份验证。
请您参考如下方法:
理解这个问题有点老了,我希望以下内容对那些寻找问题正确答案的人有所帮助
OP 询问的不是 token 失效,而是如何在用户身份验证成功通过并且有效的 access_token 或 authentication_code(用于随后获取 access_token)返回客户端后立即使 Spring OAuth2 服务器上的 httpSession 失效。
这个用例仍然没有开箱即用的解决方案。但是可以找到 spring-security-oauth 最活跃的贡献者 Dave Syer 的工作解决方法 here on GitHub
只需从那里复制代码:
@Service
@Aspect
public class SessionInvalidationOauth2GrantAspect {
private static final String FORWARD_OAUTH_CONFIRM_ACCESS = "forward:/oauth/confirm_access";
private static final Logger logger = Logger.getLogger(SessionInvalidationOauth2GrantAspect.class);
@AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
public void authorizationAdvice(JoinPoint joinpoint, ModelAndView result) throws Throwable {
// If we're not going to the confirm_access page, it means approval has been skipped due to existing access
// token or something else and they'll be being sent back to app. Time to end session.
if (!FORWARD_OAUTH_CONFIRM_ACCESS.equals(result.getViewName())) {
invalidateSession();
}
}
@AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
public void authorizationAdvice(JoinPoint joinpoint, View result) throws Throwable {
// Anything returning a view and not a ModelView is going to be redirecting outside of the app (I think).
// This happens after the authorize approve / deny page with the POST to /oauth/authorize. This is the time
// to kill the session since they'll be being sent back to the requesting app.
invalidateSession();
}
@AfterThrowing(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", throwing = "error")
public void authorizationErrorAdvice(JoinPoint joinpoint) throws Throwable {
invalidateSession();
}
private void invalidateSession() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
HttpSession session = request.getSession(false);
if (session != null) {
logger.warn(String.format("As part of OAuth application grant processing, invalidating session for request %s", request.getRequestURI()));
session.invalidate();
SecurityContextHolder.clearContext();
}
}
}
添加 pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
另一种解决方案可能是将 session 超时设置为一些非常小的值。实现这一点的最简单方法是将以下内容放入 application.yml 配置:
server:
session:
timeout: 1
但这不是理想的解决方案,因为提供者的最小值可能是 1(为无限 session 保留零)并且它以分钟而不是秒为单位