一、SpringShiroFilter
1.继承关系
SpringShiroFilter就是shiro-web框架的核心过滤器,继承关系如下:
类实体(一个内部类):
private static final class SpringShiroFilter extends AbstractShiroFilter {
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
} else {
this.setSecurityManager(webSecurityManager);
if (resolver != null) {
this.setFilterChainResolver(resolver);
}
}
}
}
二、核心过滤器实例化过程源码分析
1.配置类中配置ShiroFilterFactoryBean的@Bean对象
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
shiroFilterFactoryBean.setUnauthorizedUrl("/pub/no_permission");
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("authc", new JWTFilter());
shiroFilterFactoryBean.setFilters(filterMap);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 这里配置路径是不带server.servlet.context-path: /admin的
filterChainDefinitionMap.put("/auth/pub/**", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/**", "authc"); // 最后添加防止漏配
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
这是实例化核心过滤器的入口,ShiroFilterFactoryBean是一个实现了FactoryBean接口的类,可以看出会通过getObject()方法获取核心过滤器的对象。
2.ShiroFilterFactoryBean源码分析
可以看到ShiroFilterFactoryBean实现了FactoryBean和BeanPostProcessor接口,是一个生产bean的类。
public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor {
private static final transient Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);
// 重要的安全管理器,服务shiro的整个生命周期
private SecurityManager securityManager;
// 保存自定义的Filter
private Map<String, Filter> filters = new LinkedHashMap();
// 保存配置的路径和处理filter之间的关系,注意是有序的
private Map<String, String> filterChainDefinitionMap = new LinkedHashMap();
// 登录接口路径
private String loginUrl;
// 登录成功后跳转到的路径
private String successUrl;
// 无权限跳转的路径
private String unauthorizedUrl;
// shiro核心过滤器实例引用
private AbstractShiroFilter instance;
public ShiroFilterFactoryBean() {
}
// ......
// 获取shiro核心过滤器对象,被springIOC调用
public Object getObject() throws Exception {
if (this.instance == null) {
this.instance = this.createInstance();
}
return this.instance;
}
// FactoryBean返回的实例类型
public Class getObjectType() {
return ShiroFilterFactoryBean.SpringShiroFilter.class;
}
// FactoryBean返回的实例是否单例,单例
public boolean isSingleton() {
return true;
}
// ......
//
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Filter) {
log.debug("Found filter chain candidate filter '{}'", beanName);
Filter filter = (Filter)bean;
this.applyGlobalPropertiesIfNecessary(filter);
this.getFilters().put(beanName, filter);
} else {
log.trace("Ignoring non-Filter bean '{}'", beanName);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// ......
}
既然是一个FactoryBean就从getObject()方法下手一步步的分析吧
public Object getObject() throws Exception {
if (this.instance == null) {
this.instance = this.createInstance();// 向下继续
}
return this.instance;
}
protected AbstractShiroFilter createInstance() throws Exception {
log.debug("Creating Shiro Filter instance.");
// 获取配置的核心SecurityManager
SecurityManager securityManager = this.getSecurityManager();
String msg;
if (securityManager == null) {
msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
} else if (!(securityManager instanceof WebSecurityManager)) {
msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
} else {
// 【2.1】创建过滤器链管理器
FilterChainManager manager = this.createFilterChainManager();
// 【2.2】创建一个默认的路径匹配过滤器链解析器
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
// 这里就是简单替换默认构造创建的FilterChainManager,使用【2.1】加工好的
chainResolver.setFilterChainManager(manager);
// 【2.3】使用过滤器链管理器、解析器创建shiro核心过滤器对象返回
return new ShiroFilterFactoryBean.SpringShiroFilter((WebSecurityManager)securityManager, chainResolver);
}
}
2.1.创建过滤器链管理器
protected FilterChainManager createFilterChainManager() {
// 【2.1.1】创建默认的过滤器链管理器对象,这里添加了一些默认的过滤器
DefaultFilterChainManager manager = new DefaultFilterChainManager();
Map<String, Filter> defaultFilters = manager.getFilters();
Iterator var3 = defaultFilters.values().iterator();
// 【2.1.2】遍历默认的过滤器进行需要性的全局那三个路径的配置
while(var3.hasNext()) {
Filter filter = (Filter)var3.next();
this.applyGlobalPropertiesIfNecessary(filter);
}
// 遍历自定义过滤器进行需要性的全局那三个路径的配置,配置过滤器别名,
// 并覆盖性的添加到默认的过滤器链管理器中
Map<String, Filter> filters = this.getFilters();
String name;
Filter filter;
if (!CollectionUtils.isEmpty(filters)) {
for(Iterator var10 = filters.entrySet().iterator(); var10.hasNext(); manager.addFilter(name, filter, false)) {
Entry<String, Filter> entry = (Entry)var10.next();
name = (String)entry.getKey();
filter = (Filter)entry.getValue();
this.applyGlobalPropertiesIfNecessary(filter);
if (filter instanceof Nameable) {
((Nameable)filter).setName(name);
}
}
}
// 【2.1.3】根据配置的路径和处理filter之间的关系map进行路径与filter之间的关联处理
Map<String, String> chains = this.getFilterChainDefinitionMap();
if (!CollectionUtils.isEmpty(chains)) {
Iterator var12 = chains.entrySet().iterator();
while(var12.hasNext()) {
Entry<String, String> entry = (Entry)var12.next();
String url = (String)entry.getKey();
String chainDefinition = (String)entry.getValue();
// 配置filter负责处理的路径,重点,重点,重点......
manager.createChain(url, chainDefinition);
}
}
return manager;
}
2.1.1.添加默认的过滤器(12个)
public DefaultFilterChainManager() {
this.addDefaultFilters(false);
}
protected void addDefaultFilters(boolean init) {
// DefaultFilter是一个枚举类,里面就保存了那12个过滤器,进去看一下
DefaultFilter[] var2 = DefaultFilter.values();
int var3 = var2.length;
// 循环遍历将12个过滤器添加到默认的过滤器链管理器中
for(int var4 = 0; var4 < var3; ++var4) {
DefaultFilter defaultFilter = var2[var4];
this.addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
}
}
public enum DefaultFilter {
anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class),
authcBasic(BasicHttpAuthenticationFilter.class),
authcBearer(BearerHttpAuthenticationFilter.class),
logout(LogoutFilter.class),
noSessionCreation(NoSessionCreationFilter.class),
perms(PermissionsAuthorizationFilter.class),
port(PortFilter.class),
rest(HttpMethodPermissionFilter.class),
roles(RolesAuthorizationFilter.class),
ssl(SslFilter.class),
user(UserFilter.class);
2.1.2 默认过滤器全局需要性配置三路径
private void applyGlobalPropertiesIfNecessary(Filter filter) {
// 如果需要配置登录路径
this.applyLoginUrlIfNecessary(filter);
// 如果需要配置登录成功跳转路径
this.applySuccessUrlIfNecessary(filter);
// 如果需要配置无访问权限跳转的路径
this.applyUnauthorizedUrlIfNecessary(filter);
}
// 如果需要配置登录路径
private void applyLoginUrlIfNecessary(Filter filter) {
String loginUrl = this.getLoginUrl();
// 如果是AccessControlFilter过滤器
if (StringUtils.hasText(loginUrl) && filter instanceof AccessControlFilter) {
AccessControlFilter acFilter = (AccessControlFilter)filter;
String existingLoginUrl = acFilter.getLoginUrl();
// 如果过滤器没有自定义配置这个路径就配置全局路径
if ("/login.jsp".equals(existingLoginUrl)) {
acFilter.setLoginUrl(loginUrl);
}
}
}
// 如果需要配置登录成功跳转路径
private void applySuccessUrlIfNecessary(Filter filter) {
String successUrl = this.getSuccessUrl();
// 如果是AuthenticationFilter过滤器
if (StringUtils.hasText(successUrl) && filter instanceof AuthenticationFilter) {
AuthenticationFilter authcFilter = (AuthenticationFilter)filter;
String existingSuccessUrl = authcFilter.getSuccessUrl();
// 如果过滤器没有自定义配置这个路径就配置全局路径
if ("/".equals(existingSuccessUrl)) {
authcFilter.setSuccessUrl(successUrl);
}
}
}
// 如果需要配置无访问权限跳转的路径
private void applyUnauthorizedUrlIfNecessary(Filter filter) {
String unauthorizedUrl = this.getUnauthorizedUrl();
// 如果是AuthenticationFilter过滤器
if (StringUtils.hasText(unauthorizedUrl) && filter instanceof AuthorizationFilter) {
AuthorizationFilter authzFilter = (AuthorizationFilter)filter;
String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl();
// 如果过滤器没有自定义配置这个路径就配置全局路径
if (existingUnauthorizedUrl == null) {
authzFilter.setUnauthorizedUrl(unauthorizedUrl);
}
}
}
2.1.3 路径和处理filter之间关系处理
先说结论,路径和 filter配置中,一个路径可以配置多个filter,配置方式如下:
filterChainDefinitionMap.put("/auth/pub/**", "authc,perms[amdin,guest],roles[amdin]");
—————————————————————分割线——————————————————
// chainName就是配置的url
// chainDefinition就是filter名和规则,map的值
public void createChain(String chainName, String chainDefinition) {
if (!StringUtils.hasText(chainName)) {
throw new NullPointerException("chainName cannot be null or empty.");
} else if (!StringUtils.hasText(chainDefinition)) {
throw new NullPointerException("chainDefinition cannot be null or empty.");
} else {
if (log.isDebugEnabled()) {
log.debug("Creating chain [" + chainName + "] from String definition [" + chainDefinition + "]");
}
// 处理map的值,比如chainDefinition=“perms[admin,role],kk[dd,ee],auth”
// 处理完后为["perms[admin,role]","kk[dd,ee]",auth]
String[] filterTokens = this.splitChainDefinition(chainDefinition);
String[] var4 = filterTokens;
int var5 = filterTokens.length;
// 循环遍历处理过的map值的数组
for(int var6 = 0; var6 < var5; ++var6) {
String token = var4[var6];
// 比如token=“perms[dd,ee,ff]”,处理完后为["perms","dd,ee,ff"]
String[] nameConfigPair = this.toNameConfigPair(token);
// 建立关系
this.addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);
}
}
}
// chainName就是url
// filterName就是过滤器名
// chainSpecificFilterConfig就是规则
public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) {
if (!StringUtils.hasText(chainName)) {
throw new IllegalArgumentException("chainName cannot be null or empty.");
} else {
Filter filter = this.getFilter(filterName);
if (filter == null) {
throw new IllegalArgumentException("There is no filter with name '" + filterName + "' to apply to chain [" + chainName + "] in the pool of available Filters. Ensure a filter with that name/path has first been registered with the addFilter method(s).");
} else {
// 重点,重点,重点----这里就配置此filter负责处理的路径和处理规则
this.applyChainConfig(chainName, filter, chainSpecificFilterConfig);
// 这里可以看出一个路径可以配置多个filter
NamedFilterList chain = this.ensureChain(chainName);
chain.add(filter);
}
}
}
2.2. 创建一个默认的路径匹配过滤器链解析器
public PathMatchingFilterChainResolver() {
this.filterChainManager = new DefaultFilterChainManager();
}
跟【2.1.1.添加默认的过滤器(12个)】逻辑一样了
public DefaultFilterChainManager() {
this.addDefaultFilters(false);
}
2.3. 使用过滤器链管理器、解析器创建shiro核心过滤器对象返回
有了SecurityManager和FilterChainResolver,shiro的核心过滤器就可以在web中逍遥称霸了
private static final class SpringShiroFilter extends AbstractShiroFilter {
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
} else {
// 设置SecurityManager
this.setSecurityManager(webSecurityManager);
if (resolver != null) {
// 设置FilterChainResolver
this.setFilterChainResolver(resolver);
}
}
}
}
三、shiro核心过滤器调用过程分析
SpringShiroFilter是shiro的核心过滤器,继承了AbstractShiroFilter并简单的设置了两个属性的值**(WebSecurityManager,FilterChainResolver),所以直接看AbstractShiroFilter的doFilterInternal**方法
/*AbstractShiroFilter*/
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain) throws ServletException, IOException {
Throwable t = null;
try {
// 将HttpServletRequest包装成shiro的HttpServletRequest
final ServletRequest request = this.prepareServletRequest(servletRequest, servletResponse, chain);
// 将HttpServletResponse包装成shiro的HttpServletResponse
final ServletResponse response = this.prepareServletResponse(request, servletResponse, chain);
// 【1】重点,重点,重点------创建用户主体Subject
Subject subject = this.createSubject(request, response);
// 异步执行shiro维护的过滤器链
subject.execute(new Callable() {
public Object call() throws Exception {
// 【2】更新session最后访问时间
AbstractShiroFilter.this.updateSessionLastAccessTime(request, response);
// 【3】执行shiro过滤器链
AbstractShiroFilter.this.executeChain(request, response, chain);
return null;
}
});
} catch (ExecutionException var8) {
t = var8.getCause();
} catch (Throwable var9) {
t = var9;
}
// 执行shiro维护的过滤器链之前异常检验
if (t != null) {
if (t instanceof ServletException) {
throw (ServletException)t;
} else if (t instanceof IOException) {
throw (IOException)t;
} else {
String msg = "Filtered request failed.";
throw new ServletException(msg, t);
}
}
}
1.创建用户主体Subject
这是一个重点
protected WebSubject createSubject(ServletRequest request, ServletResponse response) {
// 根据传入的SecurityManager和request、response创建一个WebSubject
return (new Builder(this.getSecurityManager(), request, response)).buildWebSubject();
}
/**WebSubject**/
public Builder(SecurityManager securityManager, ServletRequest request, ServletResponse response) {
// 【1.1】调用父构造器,创建SubjectContext
super(securityManager);
if (request == null) {
throw new IllegalArgumentException("ServletRequest argument cannot be null.");
} else if (response == null) {
throw new IllegalArgumentException("ServletResponse argument cannot be null.");
} else {
this.setRequest(request);
this.setResponse(response);
}
}
1.1.在Builder中创建SubjectContext
/** org.apache.shiro.subject.Builder **/
public Builder(SecurityManager securityManager) {
if (securityManager == null) {
throw new NullPointerException("SecurityManager method argument cannot be null.");
} else {
this.securityManager = securityManager;
// 创建SubjectContext,这里需要重点注意一下,是调用WebSubject中的方法,不是Subject中的方法
this.subjectContext = this.newSubjectContextInstance();
if (this.subjectContext == null) {
throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' cannot be null.");
} else {
this.subjectContext.setSecurityManager(securityManager);
}
}
}
这里需要重点注意一下,是调用WebSubject中的方法,不是Subject中的方法
/*org.apache.shiro.web.subject.WebSubject*/
protected SubjectContext newSubjectContextInstance() {
return new DefaultWebSubjectContext();
}
看一看DefaultWebSubjectContext是个啥,就是定义了一堆静态属性,它的父类还定义了一堆静态属性
public class DefaultWebSubjectContext extends DefaultSubjectContext implements WebSubjectContext {
private static final long serialVersionUID = 8188555355305827739L;
private static final String SERVLET_REQUEST = DefaultWebSubjectContext.class.getName() + ".SERVLET_REQUEST";
private static final String SERVLET_RESPONSE = DefaultWebSubjectContext.class.getName() + ".SERVLET_RESPONSE";
public DefaultWebSubjectContext() {
}
// ......
}
public class DefaultSubjectContext extends MapContext implements SubjectContext {
private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER";
private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID";
private static final String AUTHENTICATION_TOKEN = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_TOKEN";
private static final String AUTHENTICATION_INFO = DefaultSubjectContext.class.getName() + ".AUTHENTICATION_INFO";
private static final String SUBJECT = DefaultSubjectContext.class.getName() + ".SUBJECT";
private static final String PRINCIPALS = DefaultSubjectContext.class.getName() + ".PRINCIPALS";
private static final String SESSION = DefaultSubjectContext.class.getName() + ".SESSION";
private static final String AUTHENTICATED = DefaultSubjectContext.class.getName() + ".AUTHENTICATED";
private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST";
public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED";
public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY";
public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY";
private static final transient Logger log = LoggerFactory.getLogger(DefaultSubjectContext.class);
public DefaultSubjectContext() {
}
// ......
}
1.2.通过Builder创建WebSubject
public WebSubject buildWebSubject() {
// 调用父类的构建方法,看下面
Subject subject = super.buildSubject();
if (!(subject instanceof WebSubject)) {
String msg = "Subject implementation returned from the SecurityManager was not a " + WebSubject.class.getName() + " implementation. Please ensure a Web-enabled SecurityManager has been configured and made available to this builder.";
throw new IllegalStateException(msg);
} else {
return (WebSubject)subject;
}
}
public Subject buildSubject() {
// 可以看出使用我们传入的SecurityManager实例创建的Subject
return this.securityManager.createSubject(this.subjectContext);
}
这样就要看DefaultWebSecurityManager的createSubject方法啦,但是它没有这个方法,那就去看它的父类DefaultSecurityManager
public Subject createSubject(SubjectContext subjectContext) {
// 这里注意是调用DefaultWebSecurityManager中的copy方法返回的是一个DefaultWebSubjectContext
SubjectContext context = this.copy(subjectContext);
context = this.ensureSecurityManager(context);
context = this.resolveSession(context);
context = this.resolvePrincipals(context);
// 使用SubjectFactory创建Subject,DefaultSubjectFactory是默认的实现类,可以配合别的实现类
Subject subject = this.doCreateSubject(context);
// 将Subject保存到SubjectDAO中,DefaultSubjectDAO是默认的实现类,可以配合别的实现类
this.save(subject);
return subject;
}
1.2.1. 使用工厂创建Subject
protected Subject doCreateSubject(SubjectContext context) {
return this.getSubjectFactory().createSubject(context);
}
这里需要注意,上面获取的SubjectFactory的真实对象其实是在new DefaultWebSecurityManager时创建的默认***DefaultWebSubjectFactory***,返回的Subject是一个WebDelegatingSubject
/* org.apache.shiro.mgt.DefaultWebSubjectFactory */
public Subject createSubject(SubjectContext context) {
boolean isNotBasedOnWebSubject = context.getSubject() != null && !(context.getSubject() instanceof WebSubject);
// 校验是否为web环境
if (context instanceof WebSubjectContext && !isNotBasedOnWebSubject) {
WebSubjectContext wsc = (WebSubjectContext)context;
SecurityManager securityManager = wsc.resolveSecurityManager();
// 解析session
Session session = wsc.resolveSession();
boolean sessionEnabled = wsc.isSessionCreationEnabled();
PrincipalCollection principals = wsc.resolvePrincipals();
boolean authenticated = wsc.resolveAuthenticated();
String host = wsc.resolveHost();
ServletRequest request = wsc.resolveServletRequest();
ServletResponse response = wsc.resolveServletResponse();
return new WebDelegatingSubject(principals, authenticated, host, session, sessionEnabled, request, response, securityManager);
} else {
return super.createSubject(context);
}
}
2.更新session最后访问时间
session的生成去看本文件所在目录下的相关文章
protected void updateSessionLastAccessTime(ServletRequest request, ServletResponse response) {
// 判断是不是web容器的HttpSession,因为shiro框架定义了自己的session,为了解耦web容器
if (!this.isHttpSessions()) {
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
// 从用户主体中获取session()
Session session = subject.getSession(false);
if (session != null) {
try {
// 如果session不为null,就在这里更新时间
session.touch();
} catch (Throwable var6) {
log.error("session.touch() method invocation has failed. Unable to update the corresponding session's last access time based on the incoming request.", var6);
}
}
}
}
}
3.执行shiro过滤器链
/*AbstractShiroFilter*/
protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain) throws IOException, ServletException {
// 【3.1】根据请求的路径获取过滤器链
FilterChain chain = this.getExecutionChain(request, response, origChain);
// 【3.2】执行已经处理好的shiro维护的过滤器链
chain.doFilter(request, response);
}
3.1根据请求的路径获取过滤器链
/*AbstractShiroFilter*/
protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
FilterChain chain = origChain;
// 这里获取到的FilterChainResolver为PathMatchingFilterChainResolver实例
FilterChainResolver resolver = this.getFilterChainResolver();
if (resolver == null) {
log.debug("No FilterChainResolver configured. Returning original FilterChain.");
return origChain;
} else {
// 【3.1.1】走这路,FilterChainResolver根据请求路径获取过滤器链
FilterChain resolved = resolver.getChain(request, response, origChain);
if (resolved != null) {
log.trace("Resolved a configured FilterChain for the current request.");
chain = resolved;
} else {
log.trace("No FilterChain configured for the current request. Using the default.");
}
return chain;
}
}
3.1.1.FilterChainResolver根据请求路径获取过滤器链
/*PathMatchingFilterChainResolver*/
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
// 获取解析器维护的FilterChainManager,这里是【2.1】步创建的DefaultFilterChainManager实例
FilterChainManager filterChainManager = this.getFilterChainManager();
if (!filterChainManager.hasChains()) {
return null;
} else {
// 获取请求url(已经去除了contextPath部分),代码很简单,这里不深入
String requestURI = this.getPathWithinApplication(request);
if (requestURI != null && !"/".equals(requestURI) && requestURI.endsWith("/")) {
requestURI = requestURI.substring(0, requestURI.length() - 1);
}
// 获取所有的ChainName(就是配置的那些ANT路径)
Iterator var6 = filterChainManager.getChainNames().iterator();
String pathPattern;
// 循环遍历直到找到第一个匹配的结果
do {
if (!var6.hasNext()) {
return null;
}
pathPattern = (String)var6.next();
if (pathPattern != null && !"/".equals(pathPattern) && pathPattern.endsWith("/")) {
pathPattern = pathPattern.substring(0, pathPattern.length() - 1);
}
// 使用AntPathMatcher进行请求url与配置的url进行匹配
} while(!this.pathMatches(pathPattern, requestURI));
if (log.isTraceEnabled()) {
log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + Encode.forHtml(requestURI) + "]. Utilizing corresponding filter chain...");
}
// 重点,重点,重点,看下面------从FilterChainManager中获取过滤器链
return filterChainManager.proxy(originalChain, pathPattern);
}
}
/*DefaultFilterChainManager*/
public FilterChain proxy(FilterChain original, String chainName) {
// 获取url对应的过滤器集合,这个集合是在核心过滤器初始化时处理好的
NamedFilterList configured = this.getChain(chainName);
if (configured == null) {
String msg = "There is no configured chain under the name/key [" + chainName + "].";
throw new IllegalArgumentException(msg);
} else {
// 获取最终的过滤器链,看下面
return configured.proxy(original);
}
}
/*SimpleNamedFilterList*/
public FilterChain proxy(FilterChain orig) {
// 返回的过滤器链,里面还维护了一个原始链(就是顶级web容器过滤器链),这样shiro内部过滤器处理完后
// 还能够交由web过滤器链处理
return new ProxiedFilterChain(orig, this);
}
3.2.执行已经处理好的shiro维护的过滤器链
ProxiedFilterChain是我们最终返回的处理指定url的过滤器链
/*ProxiedFilterChain*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// 如果过滤器不为null且没有全部执行完
if (this.filters != null && this.filters.size() != this.index) {
if (log.isTraceEnabled()) {
log.trace("Invoking wrapped filter at index [" + this.index + "]");
}
// 类似递归的过滤链调用
((Filter)this.filters.get(this.index++)).doFilter(request, response, this);
} else {
if (log.isTraceEnabled()) {
log.trace("Invoking original filter chain.");
}
// shiro过滤器链都调用完没有return或者shiro过滤器链为null则会继续调用web容器顶级的过滤器链
this.orig.doFilter(request, response);
}
}
到此shiro核心过滤器的调用过程就结束了。
如果错误之处欢迎指正!!!