一 配置
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入安全管理器-->
<property name="securityManager" ref="securityManager"/>
<!-- 设置登录URL-->
<property name="loginUrl" value="/login"/>
<property name="filters">
<util:map>
<!-- 注册authc和sysUser-->
<entry key="authc" value-ref="formAuthenticationFilter"/>
<entry key="sysUser" value-ref="sysUserFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login = authc
/logout = logout
/authenticated = authc
/** = user,sysUser
</value>
</property>
</bean>
二 filterChainDefinitions这个节点被注入的地方
ShiroFilterFactoryBean的setFilterChainDefinitions方法,会将过滤器链定义注入,代码如下:
public void setFilterChainDefinitions(String definitions) {
Ini ini = new Ini();
ini.load(definitions);
Section section = ini.getSection("urls");
if (CollectionUtils.isEmpty(section)) {
section = ini.getSection("");
}
this.setFilterChainDefinitionMap(section);
}
当执行完上面这段代码后,section的值如下:
section = {Ini$Section@5444} size = 4
"/login" -> "authc"
"/logout" -> "logout"
"/authenticated" -> "authc"
"/**" -> "user,sysUser"
同时,ShiroFilterFactoryBean的变量filterChainDefinitionMap变成下面的样子
filterChainDefinitionMap = {Ini$Section@5444} size = 4
"/login" -> "authc"
"/logout" -> "logout"
"/authenticated" -> "authc"
"/**" -> "user,sysUser"
三 filters这个节点被注入的地方
public void setFilters(Map<String, Filter> filters) {
this.filters = filters;
}
注入后的样子:
this = {ShiroFilterFactoryBean@5425}
securityManager = {DefaultWebSecurityManager@5428}
filters = {LinkedHashMap@5426} size = 2
"authc" -> {FormAuthenticationFilter@5436} "org.apache.shiro.web.filter.authc.FormAuthenticationFilter@3435b6d8"
"sysUser" -> {SysUserFilter@5438} "com.github.cakin.shiro.chapter16.web.shiro.filter.SysUserFilter@13553828"
四 protected FilterChainManager createFilterChainManager()干完活后
manager = {DefaultFilterChainManager@5681}
filterConfig = null
filters = {LinkedHashMap@5682} size = 12
"anon" -> {AnonymousFilter@5698} "anon"
"authc" -> {FormAuthenticationFilter@5751} "authc"
"authcBasic" -> {BasicHttpAuthenticationFilter@5702} "authcBasic"
"logout" -> {LogoutFilter@5704} "logout"
"noSessionCreation" -> {NoSessionCreationFilter@5706} "noSessionCreation"
"perms" -> {PermissionsAuthorizationFilter@5708} "perms"
"port" -> {PortFilter@5710} "port"
"rest" -> {HttpMethodPermissionFilter@5712} "rest"
"roles" -> {RolesAuthorizationFilter@5714} "roles"
"ssl" -> {SslFilter@5716} "ssl"
"user" -> {UserFilter@5718} "user"
"sysUser" -> {SysUserFilter@5862} "sysUser"
filterChains = {LinkedHashMap@5683} size = 4
"/login" -> {SimpleNamedFilterList@6101} size = 1
"/logout" -> {SimpleNamedFilterList@6103} size = 1
"/authenticated" -> {SimpleNamedFilterList@6105} size = 1
"/**" -> {SimpleNamedFilterList@6107} size = 2
filters:默认过滤器加配置文件中注册的过滤器。
filterChains:在配置文件中的配置值。
五 AbstractShiroFilter分析
1 如果在executeChain这个函数中加断点,通过 http://localhost:8080/chapter16/ 进行访问,该方法跑完后,变量的情况如下:
chain = {ProxiedFilterChain@6960}
orig = {ServletHandler$CachedChain@6959} "spring"
filters = {SimpleNamedFilterList@6107} size = 2
0 = {UserFilter@5718} "user"
1 = {SysUserFilter@5862} "sysUser"
index = 0
此时调用情况如下:
executeChain:449, AbstractShiroFilter (org.apache.shiro.web.servlet)
call:365, AbstractShiroFilter$1 (org.apache.shiro.web.servlet)
doCall:90, SubjectCallable (org.apache.shiro.subject.support)
call:83, SubjectCallable (org.apache.shiro.subject.support)
execute:383, DelegatingSubject (org.apache.shiro.subject.support)
doFilterInternal:362, AbstractShiroFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
invokeDelegate:344, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:261, DelegatingFilterProxy (org.springframework.web.filter)
2 从上面分析来看,会走UserFilter过滤器和SysUserFilter过滤器
UserFilter会走下面函数
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginRequest(request, response)) {
return true;
} else {
Subject subject = getSubject(request, response);
// If principal is not null, then the user is known and should be allowed access.
return subject.getPrincipal() != null;
}
}
当走到isAccessAllowed这个函数时,它的调用栈如下:
isAccessAllowed:50, UserFilter (org.apache.shiro.web.filter.authc)
onPreHandle:162, AccessControlFilter (org.apache.shiro.web.filter)
isFilterChainContinued:203, PathMatchingFilter (org.apache.shiro.web.filter)
preHandle:178, PathMatchingFilter (org.apache.shiro.web.filter)
doFilterInternal:131, AdviceFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
doFilter:66, ProxiedFilterChain (org.apache.shiro.web.servlet)
executeChain:449, AbstractShiroFilter (org.apache.shiro.web.servlet)
call:365, AbstractShiroFilter$1 (org.apache.shiro.web.servlet)
doCall:90, SubjectCallable (org.apache.shiro.subject.support)
call:83, SubjectCallable (org.apache.shiro.subject.support)
execute:383, DelegatingSubject (org.apache.shiro.subject.support)
doFilterInternal:362, AbstractShiroFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
invokeDelegate:344, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:261, DelegatingFilterProxy (org.springframework.web.filter)
SysUserFilter会走下面函数
protected boolean onPreHandle( ServletRequest request, ServletResponse response, Object mappedValue ) {
// 获得用户信息
String username = (String) SecurityUtils.getSubject().getPrincipal();
// 设置用户信息到“user”属性中
request.setAttribute(Constants.CURRENT_USER, userService.findByUsername(username));
return true;
}
当走到onPreHandle这个函数时,它的调用栈如下:
onPreHandle:38, SysUserFilter (com.github.cakin.shiro.chapter16.web.shiro.filter)
isFilterChainContinued:203, PathMatchingFilter (org.apache.shiro.web.filter)
preHandle:178, PathMatchingFilter (org.apache.shiro.web.filter)
doFilterInternal:131, AdviceFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
doFilter:66, ProxiedFilterChain (org.apache.shiro.web.servlet)
executeChain:108, AdviceFilter (org.apache.shiro.web.servlet)
doFilterInternal:137, AdviceFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
doFilter:66, ProxiedFilterChain (org.apache.shiro.web.servlet)
executeChain:449, AbstractShiroFilter (org.apache.shiro.web.servlet)
call:365, AbstractShiroFilter$1 (org.apache.shiro.web.servlet)
doCall:90, SubjectCallable (org.apache.shiro.subject.support)
call:83, SubjectCallable (org.apache.shiro.subject.support)
execute:383, DelegatingSubject (org.apache.shiro.subject.support)
doFilterInternal:362, AbstractShiroFilter (org.apache.shiro.web.servlet)
doFilter:125, OncePerRequestFilter (org.apache.shiro.web.servlet)
invokeDelegate:344, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:261, DelegatingFilterProxy (org.springframework.web.filter)
我们从调用栈可以分析出运行时刻的调用情况。