shiro过滤器源码分析

一 配置

<!-- 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)

我们从调用栈可以分析出运行时刻的调用情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值