/** * 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.web.security.internal; import com.google.common.collect.Lists; import com.google.inject.Module; import io.nuun.kernel.api.plugin.InitState; import io.nuun.kernel.api.plugin.PluginException; import io.nuun.kernel.api.plugin.context.InitContext; import io.nuun.kernel.api.plugin.request.ClasspathScanRequest; import org.apache.shiro.guice.web.GuiceShiroFilter; import org.seedstack.seed.core.SeedRuntime; import org.seedstack.seed.core.internal.AbstractSeedPlugin; import org.seedstack.seed.core.internal.configuration.ConfigurationPlugin; import org.seedstack.seed.security.internal.SecurityGuiceConfigurer; import org.seedstack.seed.security.internal.SecurityProvider; import org.seedstack.seed.web.SecurityFilter; import org.seedstack.seed.web.security.WebSecurityConfig; import org.seedstack.seed.web.spi.FilterDefinition; import org.seedstack.seed.web.spi.ListenerDefinition; import org.seedstack.seed.web.spi.SeedFilterPriority; import org.seedstack.seed.web.spi.ServletDefinition; import org.seedstack.seed.web.spi.WebProvider; import javax.servlet.Filter; import javax.servlet.ServletContext; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * This plugins adds web security. */ public class WebSecurityPlugin extends AbstractSeedPlugin implements SecurityProvider, WebProvider { private final Collection<Class<? extends Filter>> scannedFilters = new ArrayList<>(); private ServletContext servletContext; private String applicationId; private WebSecurityConfig securityConfig; @Override public String name() { return "web-security"; } @Override public void setup(SeedRuntime seedRuntime) { servletContext = seedRuntime.contextAs(ServletContext.class); } @Override public Collection<Class<?>> dependencies() { return Lists.newArrayList(ConfigurationPlugin.class); } @Override public Collection<ClasspathScanRequest> classpathScanRequests() { return classpathScanRequestBuilder().annotationType(SecurityFilter.class).build(); } @SuppressWarnings("unchecked") @Override public InitState initialize(InitContext initContext) { ConfigurationPlugin configurationPlugin = initContext.dependency(ConfigurationPlugin.class); applicationId = configurationPlugin.getApplication().getId(); securityConfig = getConfiguration(WebSecurityConfig.class); for (Class<?> filterClass : initContext.scannedClassesByAnnotationClass().get(SecurityFilter.class)) { if (Filter.class.isAssignableFrom(filterClass)) { scannedFilters.add((Class<? extends Filter>) filterClass); } else { throw new PluginException("Annotated class " + filterClass.getName() + " must implement Filter to be used in a filter chain"); } } return InitState.INITIALIZED; } @Override public Module provideMainSecurityModule(SecurityGuiceConfigurer securityGuiceConfigurer) { return servletContext != null ? new WebSecurityModule( servletContext, securityConfig, scannedFilters, applicationId, securityGuiceConfigurer ) : null; } @Override public Module provideAdditionalSecurityModule() { return null; } @Override public List<ServletDefinition> servlets() { return null; } @Override public List<FilterDefinition> filters() { FilterDefinition securityFilter = new FilterDefinition("security", GuiceShiroFilter.class); securityFilter.setPriority(SeedFilterPriority.SECURITY); securityFilter.setAsyncSupported(true); securityFilter.addMappings(new FilterDefinition.Mapping("/*")); return Lists.newArrayList(securityFilter); } @Override public List<ListenerDefinition> listeners() { return null; } }