我很难实现客户要求的功能。简而言之,他们希望能够通过管理端将他们选择的任何客户从应用程序中注销。该应用程序使用 Flex 作为前端技术并通过 AMF 访问服务器。服务器端使用 Spring Security 和 Spring BlazeDS 集成。
基本上,问题是:Spring Security 和/或 Spring BlazeDS Integration 是否提供任何开箱即用的集中式会话管理(和终止)系统?
出于概念验证的目的,我尝试使用以下代码注销所有用户并终止所有会话:
package xxx.xxx.xxx;
import java.util.List;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.User;
import flex.messaging.MessageBroker;
import flex.messaging.security.LoginCommand;
public class SessionServiceImpl {
private static final Log log = LogFactory.getLog(SessionServiceImpl.class);
private SessionRegistry sessionRegistry;
private MessageBroker messageBroker;
public SessionRegistry getSessionRegistry() {
return sessionRegistry;
}
@Autowired
public void setSessionRegistry(SessionRegistry sessionRegistry) {
log.debug("sessionregistry set");
this.sessionRegistry = sessionRegistry;
}
public MessageBroker getMessageBroker() {
return messageBroker;
}
@Autowired
public void setMessageBroker(MessageBroker messageBroker) {
log.debug("messagebroker set");
this.messageBroker = messageBroker;
}
public void logoutUser(String userName) {
log.debug("Logging out user by username: "+userName);
List<Object> principals = null;
if(sessionRegistry != null){
principals = sessionRegistry.getAllPrincipals();
}else{
log.debug("sessionRegistry null");
}
if(principals != null){
for (Object object : principals) {
User user = (User)object;
// get single users all sessions
List<SessionInformation> sessions = sessionRegistry.getAllSessions(user, false);
log.debug("Sessions list size: "+sessions.size());
if(messageBroker != null){
LoginCommand command = messageBroker.getLoginManager().getLoginCommand();
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, user.getPassword());
command.logout(usernamePasswordAuthenticationToken);
for (SessionInformation sessionInformation : sessions) {
log.debug(ReflectionToStringBuilder.toString(sessionInformation));
sessionInformation.expireNow();
sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
}
}else{
log.debug("messageBroker null");
}
if(object != null){
log.debug(ReflectionToStringBuilder.toString(object));
}else{
log.debug("object null");
}
}
}else{
log.debug("principals null");
}
}
}
不幸的是,上面的代码不起作用。据我所知,这是因为两件事:
A)LoginCommand 不是“应用程序范围的”,而是与当前会话相关联,因此它会尝试仅注销当前会话(管理员正在使用的会话)并且忽略其他会话
B) sessionInformation.expireNow() 尝试使会话过期,但如果用户设法在会话失效之前发出请求,则会话不会被破坏
从文档中我可以看到 session.invalidate() 可以直接使会话无效,但似乎我无法访问所有会话对象。
实现此类功能的最快或最聪明的方法是什么?
最好的问候, 朱卡