/*
*
* * Copyright (c) 2016. David Sowerby
* *
* * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* * the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* * specific language governing permissions and limitations under the License.
*
*/
package uk.q3c.krail.core.shiro;
import com.google.inject.Inject;
import com.vaadin.server.VaadinSession;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.session.mgt.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.UUID;
/**
* A {@link SessionManager} implementation that uses the {@link VaadinSession} for the current user to common and locate the Shiro {@link Session}. This
* tightly ties the Shiro security Session lifecycle to that of the VaadinSession allowing expiration, persistence, and clustering to be handled only in the
* Vaadin configuration rather than be duplicated in both the Vaadin and Shiro configuration.
*
* @author mpilone
*/
public class VaadinSessionManager implements SessionManager {
/**
* The session attribute name prefix used for storing the Shiro Session in the VaadinSession.
*/
public final static String SESSION_ATTRIBUTE_PREFIX = VaadinSessionManager.class.getName() + ".session.";
private static Logger log = LoggerFactory.getLogger(VaadinSessionManager.class);
/**
* The session factory used to create new sessions. In the future, it may make more sense to simply implement a
* {@link Session} that is a lightweight wrapper on the {@link VaadinSession} rather than storing a
* {@link SimpleSession} in the {@link VaadinSession}. However by using a SimpleSession, the security information
* is
* contained in a neat bucket inside the overall VaadinSession.
*/
private final SessionFactory sessionFactory;
private final VaadinSessionProvider sessionProvider;
/**
* Constructs the VaadinSessionManager.
*/
@Inject
protected VaadinSessionManager(VaadinSessionProvider sessionProvider) {
this.sessionProvider = sessionProvider;
sessionFactory = new SimpleSessionFactory();
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.session.mgt.SessionManager#start(org.apache.shiro.session .mgt.SessionContext)
*/
@Override
public Session start(SessionContext context) {
log.debug("starting VaadinSessionManager");
// Retrieve the VaadinSession for the current user.
VaadinSession vaadinSession = sessionProvider.get();
// Create a new security session using the session factory.
SimpleSession shiroSession = (SimpleSession) sessionFactory.createSession(context);
// Assign a unique ID to the session now because this session manager
// doesn't use a SessionDAO for persistence as it delegates to any
// VaadinSession configured persistence.
shiroSession.setId(UUID.randomUUID()
.toString());
// Put the security session in the VaadinSession. We use the session's ID as
// part of the key just to be safe so we can double check that the security
// session matches when it is requested in getSession.
vaadinSession.setAttribute(SESSION_ATTRIBUTE_PREFIX + shiroSession.getId(), shiroSession);
return shiroSession;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.session.mgt.SessionManager#getSession(org.apache.shiro .session.mgt.SessionKey)
*/
@Override
public Session getSession(SessionKey key) throws SessionException {
// Retrieve the VaadinSession for the current user.
VaadinSession vaadinSession = sessionProvider.get();
String attributeName = SESSION_ATTRIBUTE_PREFIX + key.getSessionId();
if (vaadinSession != null) {
// If we have a valid VaadinSession, try to get the Shiro Session.
SimpleSession shiroSession = (SimpleSession) vaadinSession.getAttribute(attributeName);
if (shiroSession != null) {
// Make sure the Shiro Session hasn't been stopped or expired (i.e. the
// user logged out).
if (shiroSession.isValid()) {
return shiroSession;
} else {
// This is an invalid or expired session so we'll clean it up.
vaadinSession.setAttribute(attributeName, null);
}
}
}
return null;
}
}