之前我们配置shiro的配置文件时,都是通过xml中的bean来配置,今天我们利用Java的注解来实现
创建一个SecurityConfig.java来设置shiro的相关信息,以及实现rememberMe的功能,设置有效的时长
SecurityConfig.java:
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.hhh.security.ShiroDBRealm;
import com.hhh.security.ShiroKeyRealm;
import com.hhh.security.XssFilter;
/**
* Shiro配置
*/
@Configuration
public class SecurityConfig implements EnvironmentAware {
private final static Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private Environment env;
@Override
public void setEnvironment(final Environment environment) {
this.env = environment;
}
/*
* 设置subjectDao,获取会话模式,设置会话模式,设置会话管理器,是否是http会话模式等操作
*/
@Bean(name = "securityManager")
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realms());
securityManager.setSessionManager(sessionManager());
//注入记住我管理器
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean(name="rememberMeManager")
public RememberMeManager rememberMeManager() {
CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
// cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
rememberMeManager.setCipherKey(Base64.decode("4AvVhdsgUs0FSA3SDFAdag=="));
//设置cookie
rememberMeManager.setCookie(rememberMeCookie());
return rememberMeManager;
}
@Bean(name="rememberMeCookie")
public Cookie rememberMeCookie() {
//设置名为rememberMe的cookie
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setMaxAge(1209600); // 两周之内记住我
return cookie;
}
protected SessionManager sessionManager() {
return new ServletContainerSessionManager();
}
/*
* realm,这里可以换成自己的书写的验证realm
*/
@Bean
public AuthorizingRealm shiroDBRealm() {
return new ShiroDBRealm();
}
@Bean
public Collection<Realm> realms() {
List<Realm> realms = new LinkedList<Realm>();
realms.add(shiroDBRealm());
return realms;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean(name = "xssFilter")
public Filter xssFilter() {
return new XssFilter();
}
@Bean(name = "shiroFilter")
public Filter shiroFilter() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
//设置登录url,通过environment这个类来实现从properties文件中读取相关的配置
shiroFilterFactoryBean.setLoginUrl(env.getProperty("loginURL"));
//设置登录成功的url
shiroFilterFactoryBean.setSuccessUrl(env.getProperty("successURL"));
//设置没通过验证的url
shiroFilterFactoryBean.setUnauthorizedUrl(env.getProperty("unauthorizedURL"));
Map<String, Filter> filters = new HashMap<String, Filter>();
filters.put("anon", new AnonymousFilter());
FormAuthenticationFilter formFilter = new FormAuthenticationFilter();
formFilter.setRememberMeParam("rememberMe");
filters.put("anthc", formFilter);
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl("/admin/login");
filters.put("logout", logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
Map<String, String> filterChainDefMap = new LinkedHashMap<String, String>();
filterChainDefMap.put("/admin/login", "anon");
filterChainDefMap.put("/admin/logout", "logout");
filterChainDefMap.put("/admin/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefMap);
try {
return (Filter) shiroFilterFactoryBean.getObject();
} catch (Exception ex) {
throw new BeanCreationException("shiroFilter", "FactoryBean throw exception on object creation", ex);
}
}
}
注意:
1.在shiro验证用到的实体类一定要注意检查是否已序列化,实现java.io.Serializable,因为如果没有序列化,则会在shiro对其进行持久化时会出错,这个错如果没有注意会后面遇到问题时会较为难找
出现错误的地方是:shiro包中的org.apache.shiro.io.DefaultSerializer<T>接口中,如下:
2.在shiro用到的实体类中包含其他的实体也得注意,也要将其序列化,不然也会出现同样的错误