/* * * * 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.Singleton; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.multibindings.OptionalBinder; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.cache.MemoryConstrainedCacheManager; import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.guice.ShiroModule; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.realm.Realm; import org.apache.shiro.session.mgt.SessionManager; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; /** * Bindings for Shiro and user related implementations * * @author David Sowerby 15 Jul 2013 */ public class DefaultShiroModule extends ShiroModule { private List<Class<? extends Realm>> realms = new ArrayList<>(); private OptionalBinder<CacheManager> cacheManagerBinder; private boolean cacheEnabled = false; public DefaultShiroModule() { super(); } @Override protected void configureShiro() { cacheManagerBinder = OptionalBinder.newOptionalBinder(binder(), CacheManager.class); bindCredentialsMatcher(); bindLoginAttemptLog(); bindRealms(); bindSubjectIdentifier(); expose(SubjectIdentifier.class); bindSubjectProvider(); expose(SubjectProvider.class); if (cacheEnabled) { bindCacheManager(); } } public DefaultShiroModule enableCache() { cacheEnabled = true; return this; } /** * Override this method to provide a different implementation of {@link CacheManager}. See http://shiro.apache.org/caching.html */ protected void bindCacheManager() { cacheManagerBinder.setBinding() .to(MemoryConstrainedCacheManager.class) .in(Singleton.class); } private void bindRealms() { if (realms.isEmpty()) { realms.add(DefaultRealm.class); } for (Class<? extends Realm> realmClass : realms) { bindRealm().to(realmClass); } } /** * Override this to provide your own {@link SubjectIdentifier} implementation */ protected void bindSubjectIdentifier() { bind(SubjectIdentifier.class).to(DefaultSubjectIdentifier.class); } /** * Override this to bind your own implementation of {@link LoginAttemptLog} */ protected void bindLoginAttemptLog() { bind(LoginAttemptLog.class).to(DefaultLoginAttemptLog.class); } /** * Override this method to bind your own {@link CredentialsMatcher} implementation */ protected void bindCredentialsMatcher() { bind(CredentialsMatcher.class).to(AlwaysPasswordCredentialsMatcher.class); } protected void bindSubjectProvider() { bind(SubjectProvider.class).to(DefaultSubjectProvider.class); // bind(Subject.class).toProvider(SubjectProvider.class); } /** * Call to add one or more {@link Realm}s. Multiple calls may be made */ public DefaultShiroModule addRealm(Class<? extends Realm> realm) { this.realms.add(realm); return this; } @Override protected void bindSecurityManager(AnnotatedBindingBuilder<? super SecurityManager> bind) { try { bind.toConstructor(KrailSecurityManager.class.getConstructor(Collection.class, Optional.class)) .asEagerSingleton(); } catch (NoSuchMethodException e) { throw new ConfigurationException("This really shouldn't happen. Either something has changed in Shiro, " + "" + "or there's a bug in ShiroModule.", e); } } @Override protected void bindSessionManager(AnnotatedBindingBuilder<SessionManager> bind) { bind.to(VaadinSessionManager.class) .asEagerSingleton(); } }