org.obiba.mica.security.SecurityManagerFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.mica.security.SecurityManagerFactory.java

Source

/*
 * Copyright (c) 2018 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.obiba.mica.security;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.util.Set;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.PasswordMatcher;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.authz.permission.PermissionResolver;
import org.apache.shiro.authz.permission.PermissionResolverAware;
import org.apache.shiro.authz.permission.RolePermissionResolver;
import org.apache.shiro.authz.permission.RolePermissionResolverAware;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.util.LifecycleUtils;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.obiba.shiro.SessionStorageEvaluator;
import org.obiba.shiro.realm.ObibaRealm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class SecurityManagerFactory implements FactoryBean<SessionsSecurityManager> {

    public static final String INI_REALM = "mica-ini-realm";

    private static final long SESSION_VALIDATION_INTERVAL = 300000l; // 5 minutes

    private static final Logger log = LoggerFactory.getLogger(SecurityManagerFactory.class);

    private final Environment environment;

    private final Set<Realm> realms;

    private final RolePermissionResolver rolePermissionResolver;

    private final PermissionResolver permissionResolver;

    private final CacheManager cacheManager;

    private SessionsSecurityManager securityManager;

    @Inject
    @Lazy
    public SecurityManagerFactory(Environment environment, Set<Realm> realms,
            RolePermissionResolver rolePermissionResolver, PermissionResolver permissionResolver,
            CacheManager cacheManager) {
        this.environment = environment;
        this.realms = realms;
        this.rolePermissionResolver = rolePermissionResolver;
        this.permissionResolver = permissionResolver;
        this.cacheManager = cacheManager;
    }

    @Override
    public SessionsSecurityManager getObject() throws Exception {
        if (securityManager == null) {
            securityManager = doCreateSecurityManager();
            SecurityUtils.setSecurityManager(securityManager);
        }
        return securityManager;
    }

    @Override
    public Class<?> getObjectType() {
        return SessionsSecurityManager.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @PreDestroy
    public void destroySecurityManager() {
        log.debug("Shutdown SecurityManager");
        // Destroy the security manager.
        SecurityUtils.setSecurityManager(null);
        LifecycleUtils.destroy(securityManager);
        securityManager = null;
    }

    private SessionsSecurityManager doCreateSecurityManager() {

        ImmutableList.Builder<Realm> builder = ImmutableList.<Realm>builder().add(micaIniRealm());

        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "agate.");
        String obibaRealmUrl = propertyResolver.getProperty("url");
        String serviceName = propertyResolver.getProperty("application.name");
        String serviceKey = propertyResolver.getProperty("application.key");

        if (!Strings.isNullOrEmpty(obibaRealmUrl)) {
            builder.add(obibaRealm(obibaRealmUrl, serviceName, serviceKey));
        }

        builder.addAll(realms);

        DefaultWebSecurityManager manager = new DefaultWebSecurityManager(builder.build());

        initializeCacheManager(manager);
        initializeSessionManager(manager);
        initializeSubjectDAO(manager);
        initializeAuthorizer(manager);
        initializeAuthenticator(manager);

        return manager;
    }

    private Realm micaIniRealm() {
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
        iniRealm.setName(INI_REALM);
        iniRealm.setRolePermissionResolver(rolePermissionResolver);
        iniRealm.setPermissionResolver(permissionResolver);
        iniRealm.setCredentialsMatcher(new PasswordMatcher());

        return iniRealm;
    }

    private Realm obibaRealm(String obibaRealmUrl, String serviceName, String serviceKey) {
        ObibaRealm oRealm = new ObibaRealm();
        oRealm.setRolePermissionResolver(rolePermissionResolver);
        oRealm.setBaseUrl(obibaRealmUrl);
        oRealm.setServiceName(serviceName);
        oRealm.setServiceKey(serviceKey);
        // Note: authentication caching is not enabled because it makes the SSO fail

        return oRealm;
    }

    private void initializeCacheManager(DefaultWebSecurityManager dsm) {
        if (dsm.getCacheManager() == null) {
            EhCacheManager ehCacheManager = new EhCacheManager();
            ehCacheManager.setCacheManager(cacheManager);
            dsm.setCacheManager(ehCacheManager);
        }
    }

    private void initializeSessionManager(DefaultWebSecurityManager dsm) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
        sessionManager.setSessionValidationInterval(SESSION_VALIDATION_INTERVAL);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        dsm.setSessionManager(sessionManager);
    }

    private void initializeSubjectDAO(DefaultWebSecurityManager dsm) {
        if (dsm.getSubjectDAO() instanceof DefaultSubjectDAO) {
            ((DefaultSubjectDAO) dsm.getSubjectDAO()).setSessionStorageEvaluator(new SessionStorageEvaluator());
        }
    }

    private void initializeAuthorizer(DefaultWebSecurityManager dsm) {
        if (dsm.getAuthorizer() instanceof ModularRealmAuthorizer) {
            ((RolePermissionResolverAware) dsm.getAuthorizer()).setRolePermissionResolver(rolePermissionResolver);
            ((PermissionResolverAware) dsm.getAuthorizer()).setPermissionResolver(permissionResolver);
        }
    }

    private void initializeAuthenticator(DefaultWebSecurityManager dsm) {
        if (dsm.getAuthenticator() instanceof ModularRealmAuthenticator) {
            ((ModularRealmAuthenticator) dsm.getAuthenticator())
                    .setAuthenticationStrategy(new FirstSuccessfulStrategy());
        }
    }
}