Shiro过滤器链

前言

本篇是学习 Shiro 中如何初始化过滤器链的

实践

  1. 首先,随便定义几个过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author cuishiying
* @date 2021-01-22
*/
public class AnonymousFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("AnonymousFilter init...");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("AnonymousFilter doFilter...");
chain.doFilter(request, response);
}

@Override
public void destroy() {
System.out.println("AnonymousFilter destroy...");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author cuishiying
* @date 2021-01-22
*/
public class FormAuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("AnonymousFilter init...");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("AnonymousFilter doFilter...");
chain.doFilter(request, response);
}

@Override
public void destroy() {
System.out.println("AnonymousFilter destroy...");
}
}
  1. 用枚举将过滤器管理起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.example.demo.shiro;

import org.springframework.objenesis.instantiator.util.ClassUtils;

import javax.servlet.Filter;

/**
* @author cuishiying
* @date 2021-01-22
*/
public enum DefaultFilter {

anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class);

private final Class<? extends Filter> filterClass;

private DefaultFilter(Class<? extends Filter> filterClass) {
this.filterClass = filterClass;
}

public Filter newInstance() {
return (Filter) ClassUtils.newInstance(this.filterClass);
}
}
  1. 创建过滤器管理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.example.demo.shiro;

import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author cuishiying
* @date 2021-01-22
*/
public class DefaultFilterChainManager {

private FilterConfig filterConfig;
private Map<String, Filter> filters;

public DefaultFilterChainManager() {
this.filters = new LinkedHashMap<String, Filter>();
addDefaultFilters(false);
}

public DefaultFilterChainManager(FilterConfig filterConfig) {
this.filters = new LinkedHashMap<String, Filter>();
setFilterConfig(filterConfig);
addDefaultFilters(true);
}

private void addDefaultFilters(boolean init) {
for (DefaultFilter defaultFilter : DefaultFilter.values()) {
addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
}
}

public Map<String, Filter> getFilters() {
return filters;
}

protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) {
Filter existing = getFilter(name);
if (existing == null) {

if (init) {
initFilter(filter);
}
this.filters.put(name, filter);
}
}

public Filter getFilter(String name) {
return this.filters.get(name);
}

protected void initFilter(Filter filter) {
FilterConfig filterConfig = getFilterConfig();
if (filterConfig == null) {
throw new IllegalStateException("FilterConfig attribute has not been set. This must occur before filter " +
"initialization can occur.");
}
try {
filter.init(filterConfig);
} catch (ServletException e) {
throw new RuntimeException(e);
}
}

public FilterConfig getFilterConfig() {
return filterConfig;
}

public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
}
  1. 测试
1
2
3
4
5
6
7
public class FilterTest {

public static void main(String[] args) {
DefaultFilterChainManager defaultFilterChainManager = new DefaultFilterChainManager();
System.out.println(defaultFilterChainManager.getFilters()); // {anon=com.example.demo.shiro.AnonymousFilter@90f6bfd, authc=com.example.demo.shiro.FormAuthenticationFilter@47f6473}
}
}
  1. spring中集成自定义的 FilterChain

一般我们想在spring中注入过滤器,会通过xml或者代码bean注入。这里我们用xml演示, 代码节选自 shiro

1
2
3
4
5
6
7
8
9
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ShiroFilter extends AbstractShiroFilter {

/**
* Configures this instance based on the existing {@link org.apache.shiro.web.env.WebEnvironment} instance
* available to the currently accessible {@link #getServletContext() servletContext}.
*
* @see org.apache.shiro.web.env.EnvironmentLoaderListener
* @since 1.2
*/
@Override
public void init() throws Exception {
WebEnvironment env = WebUtils.getRequiredWebEnvironment(getServletContext());

setSecurityManager(env.getWebSecurityManager());

FilterChainResolver resolver = env.getFilterChainResolver();
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FilterChainResolver {

private DefaultFilterChainManager filterChainManager;

public FilterChainResolver() {
this.filterChainManager = new DefaultFilterChainManager();
}

public FilterChainResolver(FilterConfig filterConfig) {
this.filterChainManager = new DefaultFilterChainManager(filterConfig);
}

public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
DefaultFilterChainManager filterChainManager = getFilterChainManager();
// 遍历filterChainManager中的过滤器配置, 匹配requestURI与配置的pathPattern, 找出匹配的FilterChain即返回
return null;
}

public DefaultFilterChainManager getFilterChainManager() {
return filterChainManager;
}
}

最后

本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。