/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.security.internal; import com.google.common.base.Strings; import com.google.inject.Injector; import com.google.inject.PrivateModule; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; import org.apache.shiro.realm.Realm; import org.seedstack.seed.security.PrincipalCustomizer; import org.seedstack.seed.security.RoleMapping; import org.seedstack.seed.security.RolePermissionResolver; import org.seedstack.seed.security.Scope; import org.seedstack.seed.security.SecurityConfig; import org.seedstack.seed.security.SecuritySupport; import javax.inject.Inject; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; class SecurityInternalModule extends PrivateModule { private final Map<String, Class<? extends Scope>> scopeClasses; private final SecurityConfigurer securityConfigurer; SecurityInternalModule(SecurityConfigurer securityConfigurer, Map<String, Class<? extends Scope>> scopeClasses) { this.securityConfigurer = securityConfigurer; this.scopeClasses = scopeClasses; } @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void configure() { bind(SecurityConfig.class).toInstance(securityConfigurer.getSecurityConfiguration()); bind(ShiroRealmAdapter.class); bind(new TypeLiteral<Map<String, Class<? extends Scope>>>() { }).toInstance(scopeClasses); bind(SecuritySupport.class).to(ShiroSecuritySupport.class); bindRealms(); Multibinder<PrincipalCustomizer> principalCustomizers = Multibinder.newSetBinder(binder(), PrincipalCustomizer.class); for (Class<? extends PrincipalCustomizer> customizerClass : securityConfigurer.getPrincipalCustomizers()) { principalCustomizers.addBinding().to(customizerClass); } expose(new TypeLiteral<Set<Realm>>() { }); expose(new TypeLiteral<Set<PrincipalCustomizer>>() { }); expose(SecuritySupport.class); expose(SecurityConfig.class); } private void bindRealms() { Collection<RealmConfiguration> realms = securityConfigurer.getConfigurationRealms(); Set<Class<? extends org.seedstack.seed.security.Realm>> apiRealmClasses = new HashSet<>(); for (RealmConfiguration realm : realms) { bind(realm.getRealmClass()); apiRealmClasses.add(realm.getRealmClass()); bind(RolePermissionResolver.class).annotatedWith(Names.named(realm.getName() + "-role-permission-resolver")).to(realm.getRolePermissionResolverClass()); bind(RoleMapping.class).annotatedWith(Names.named(realm.getName() + "-role-mapping")).to(realm.getRoleMappingClass()); } bind(new TypeLiteral<Set<Class<? extends org.seedstack.seed.security.Realm>>>() { }).toInstance(apiRealmClasses); bind(new TypeLiteral<Set<Realm>>() { }).toProvider(new RealmProvider(securityConfigurer.getSecurityConfiguration())).asEagerSingleton(); } static class RealmProvider implements Provider<Set<Realm>> { private final SecurityConfig securityConfiguration; @Inject private Injector injector; @Inject private Set<Class<? extends org.seedstack.seed.security.Realm>> realmClasses; private Set<Realm> realms; RealmProvider(SecurityConfig securityConfiguration) { this.securityConfiguration = securityConfiguration; } @Override public Set<Realm> get() { if (realms == null) { realms = new HashSet<>(); for (Class<? extends org.seedstack.seed.security.Realm> seedRealmClass : realmClasses) { ShiroRealmAdapter realmAdapter = injector.getInstance(ShiroRealmAdapter.class); realmAdapter.setRealm(injector.getInstance(seedRealmClass)); if (securityConfiguration.cache().isEnabled()) { realmAdapter.setCachingEnabled(true); // Authentication cache realmAdapter.setAuthenticationCachingEnabled(securityConfiguration.cache().authentication().isEnabled()); String authenticationCacheName = securityConfiguration.cache().authentication().getName(); if (!Strings.isNullOrEmpty(authenticationCacheName)) { realmAdapter.setAuthenticationCacheName(authenticationCacheName); } // Authorization cache realmAdapter.setAuthorizationCachingEnabled(securityConfiguration.cache().authorization().isEnabled()); String authorizationCacheName = securityConfiguration.cache().authorization().getName(); if (!Strings.isNullOrEmpty(authorizationCacheName)) { realmAdapter.setAuthorizationCacheName(authorizationCacheName); } } else { realmAdapter.setCachingEnabled(false); } realms.add(realmAdapter); } } return realms; } } }