package com.aperture_software.glados_wiki.spring.root; import com.aperture_software.glados_wiki.servlets.WebappPath; import com.aperture_software.glados_wiki.shiro.MyRealm; import com.aperture_software.glados_wiki.spring.shiro.ShiroContextInitialize; import com.aperture_software.glados_wiki.spring.shiro.ShiroSessionHandlerMethodArgumentResolver; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.ObjectUtils; import org.apache.shiro.authc.*; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.web.filter.authc.LogoutFilter; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Import; /** * Created by jhyun on 13. 12. 21. */ @Import(value = {ShiroContextInitialize.class}) @Configuration public class ShiroContext { private static Logger LOG = LoggerFactory.getLogger(ShiroContext.class); @Bean public SessionDAO sessionDAO() { return new EnterpriseCacheSessionDAO(); } @Bean public SessionManager sessionManager(SessionDAO sessionDAO) { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionDAO(sessionDAO); return sessionManager; } @Bean public SecurityManager securityManager(net.sf.ehcache.CacheManager cacheManager, SessionManager sessionManager, MyRealm myRealm) { DefaultWebSecurityManager sm = new DefaultWebSecurityManager(); registLoggingAuthenticationListener(sm); // EhCacheManager cm = new EhCacheManager(); cm.setCacheManager(cacheManager); sm.setCacheManager(cm); sm.setSessionManager(sessionManager); // realm. Preconditions.checkNotNull(myRealm); sm.setRealm(myRealm); // return sm; } private void registLoggingAuthenticationListener(DefaultWebSecurityManager sm) { if (sm.getAuthenticator() instanceof AbstractAuthenticator) { AbstractAuthenticator aa = (AbstractAuthenticator) sm.getAuthenticator(); aa.getAuthenticationListeners().add(new AuthenticationListener() { @Override public void onSuccess(AuthenticationToken token, AuthenticationInfo info) { LOG.debug(String.format("AUTHENTICATE SUCCESS -- token=[%s] / info=[%s]", token, info)); } @Override public void onFailure(AuthenticationToken token, AuthenticationException ae) { LOG.warn(String.format("AUTHENTICATE FAIL -- token=[%s]", token), ae); } @Override public void onLogout(PrincipalCollection principals) { LOG.debug(String.format("LOGGED-OUT -- principals=[%s]", principals)); } }); } else { LOG.warn("NOT AN AbstractAuthenticator!!! NO-AuthenticationListener!!!"); } } @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean public LogoutFilter logoutFilter() { LogoutFilter logoutFilter = new LogoutFilter(); logoutFilter.setRedirectUrl(WebappPath.getWebappPath() + "/"); return logoutFilter; } // NOTE: roles.unauthorizedUrl, perms.unauthorizedUrl 같은 것들도 각각의 필터를 생성하고 설정. @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager, LogoutFilter logoutFilter) { ShiroFilterFactoryBean sffb = new ShiroFilterFactoryBean(); sffb.setSecurityManager(securityManager); // sffb.getFilters().put("logout", logoutFilter); // sffb.setLoginUrl(WebappPath.getWebappPath() + "/a/user/loginForm"); // TODO: ?? sffb.setSuccessUrl("/"); sffb.setUnauthorizedUrl(WebappPath.getWebappPath() + "/a/error/unauthorized"); // sffb.setFilterChainDefinitionMap(ImmutableMap.<String, String>builder() .put(WebappPath.getWebappPath() + "/a/user/loginForm", "authc") .put(WebappPath.getWebappPath() + "/a/user/logout", "logout") .put(WebappPath.getWebappPath() + "/a/shiro/restricted", "user") .put(WebappPath.getWebappPath() + "/a/shiro/privileged", "user, roles[never_given_permission]") .build()); // LOG.debug(ObjectUtils.toString(sffb.getFilters())); // return sffb; } @Bean public ShiroSessionHandlerMethodArgumentResolver shiroSessionHandlerMethodArgumentResolver() { return new ShiroSessionHandlerMethodArgumentResolver(); } @DependsOn(value = {"lifecycleBeanPostProcessor"}) @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { return new DefaultAdvisorAutoProxyCreator(); } @Bean AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager); return aasa; } }