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;
}
}