shiro与springboot整合原理
⾸先在我们之前的chapter1⽂章中讲到shiro配置类中有这个⽅法:
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 配置不会被拦截的链接顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
/
/配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout.html", "logout");
//<!-- 过滤链定义,从上向下顺序执⾏,⼀般将/**放在最为下边 -->:这是⼀个坑呢,⼀不⼩⼼代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会⾃动寻Web⼯程根⽬录下的"/login.jsp"页⾯
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index.html");
//未授权界⾯;
shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
就从这个⽅法开始讲shiro与springboot是如何整合在⼀起的。⾸先该⽅法中实例化了⼀个ShiroFilterFactoryBean,继承结构为:
可以明显看出,该类实现了Spring中的FactoryBean和BeanPostProcessor接⼝,来看看都做了那些事情
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/
/如果该bean实现了java.servlet.Filter接⼝,则把该bean添加到该类的内部变量
//Map<String,Filter> filters;中,以后再传到过滤器链中
if (bean instanceof Filter) {
Filter filter = (Filter) bean;
//如何该过滤器继承了AccessControlFilter,AuthenticationFilter,AuthorizationFilter
//⽽且没有更改默认的登录url,登录成功url,权限失败url,就设置成上⾯我们在配置类中传⼊的url,否则不⽤我们上⾯设置的url
applyGlobalPropertiesIfNecessary(filter);
getFilters().put(beanName, filter);
} else {
}
return bean;
}
//没做啥事,直接返回
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
springboot是啥
return bean;
}
然后再看BeanFactory接⼝中的⽅法实现,此⽅法的主要⽬的是⽣成shiro的⼀个过滤器,拦截每⼀个request请求,该过滤器中⼜包含所有(shiro内部和我们⾃⼰添加进去的)。
public Object getObject() throws Exception {
if (instance == null) {
instance = createInstance();
}
return instance;
}
此⽅法主要验证securityManager实例的有效性,就是我们上⾯注⼊到ShiroFilterBeanFactory中的那个。然后,哈哈,这⾥会创建⼀个默认的过滤器链管理类,shiro内部⾃⼰实现的,这就涉及到了过滤器设计模式了。关于shiro这⾥的过滤器设计代码就不在这⾥分析了,会单独写篇⽂章分析。最后把securityManager和chainResolver传⼊SpringShiroFilter
protected AbstractShiroFilter createInstance() throws Exception {
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
在哪⾥把SecurityManager保存在 ThreadContext 中的那 ?原来是执⾏Filter 的init⽅法的时候:
public final void init(FilterConfig filterConfig) throws ServletException {
setFilterConfig(filterConfig);
try {
onFilterConfigSet();
} catch (Exception e) {
if (e instanceof ServletException) {
throw (ServletException) e;
} else {
if (log.isErrorEnabled()) {
<("Unable to start Filter: [" + e.getMessage() + "].", e);
}
throw new ServletException(e);
}
}
}
protected final void onFilterConfigSet() throws Exception {
/
/added in 1.2 for SHIRO-287:
applyStaticSecurityManagerEnabledConfig();
init();
ensureSecurityManager();
//added in 1.2 for SHIRO-287:
if (isStaticSecurityManagerEnabled()) {
SecurityUtils.setSecurityManager(getSecurityManager());
}
}
SecurityUtils.setSecurityManager(getSecurityManager());真想⼤⽩了,所以我们能过该⼯具类获取到SecurityManager

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。