Shiro 시리즈 튜 토리 얼 ShiroFilter 소스 코드 분석
14982 단어 Shiro
DefaultFilter
// shiro
public enum DefaultFilter {
anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class),
authcBasic(BasicHttpAuthenticationFilter.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);
private final Class extends Filter> filterClass;
private DefaultFilter(Class extends Filter> filterClass) {
this.filterClass = filterClass;
}
public Filter newInstance() {
return (Filter) ClassUtils.newInstance(this.filterClass);
}
public Class extends Filter> getFilterClass() {
return this.filterClass;
}
public static Map createInstanceMap(FilterConfig config) {
Map filters = new LinkedHashMap(values().length);
for (DefaultFilter defaultFilter : values()) {
Filter filter = defaultFilter.newInstance();
if (config != null) {
try {
filter.init(config);
} catch (ServletException e) {
String msg = "Unable to correctly init default filter instance of type " +
filter.getClass().getName();
throw new IllegalStateException(msg, e);
}
}
filters.put(defaultFilter.name(), filter);
}
return filters;
}
}
DefaultFilterChainManager
public class DefaultFilterChainManager implements FilterChainManager {
private FilterConfig filterConfig;
// shiro filter
//roles RolesAuthorizationFilter
//ssl SslFilter
//
private Map filters;
// filter
// URL =》 /index.jsp=authc, roles[admin,user], perms[file:edit]
// key:/index.jsp value: list[FormAuthenticationFilter ,RolesAuthorizationFilter ,PermissionsAuthorizationFilter ]
private Map filterChains;
public DefaultFilterChainManager() {
this.filters = new LinkedHashMap();
this.filterChains = new LinkedHashMap();
// shiro filter filters
addDefaultFilters(false);
}
public DefaultFilterChainManager(FilterConfig filterConfig) {
this.filters = new LinkedHashMap();
this.filterChains = new LinkedHashMap();
// shiro filter filters
setFilterConfig(filterConfig);
addDefaultFilters(true);
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public Map getFilters() {
return filters;
}
@SuppressWarnings({"UnusedDeclaration"})
public void setFilters(Map filters) {
this.filters = filters;
}
public Map getFilterChains() {
return filterChains;
}
@SuppressWarnings({"UnusedDeclaration"})
public void setFilterChains(Map filterChains) {
this.filterChains = filterChains;
}
public Filter getFilter(String name) {
return this.filters.get(name);
}
public void addFilter(String name, Filter filter) {
addFilter(name, filter, false);
}
public void addFilter(String name, Filter filter, boolean init) {
addFilter(name, filter, init, true);
}
// filterChain
// URL /index.jsp=authc, roles[admin,user], perms[file:edit]
// chainName=/index.jsp chainDefinition=authc, roles[admin,user], perms[file:edit]
public void createChain(String chainName, String chainDefinition) {
//parse the value by tokenizing it to get the resulting filter-specific config entries
//
//e.g. for a value of
//
// "authc, roles[admin,user], perms[file:edit]"
//
// the resulting token array would equal
//
// { "authc", "roles[admin,user]", "perms[file:edit]" }
//
// authc, roles[admin,user], perms[file:edit]
// ["authc", "roles[admin,user]", "perms[file:edit]"]
String[] filterTokens = splitChainDefinition(chainDefinition);
//each token is specific to each filter.
//strip the name and extract any filter-specific config between brackets [ ]
for (String token : filterTokens) {
// authc returned[0] == authc returned[1] == null
// roles[admin,user] returned[0] == roles returned[1] == admin,user
String[] nameConfigPair = toNameConfigPair(token);
// filter list
// : chainName=/index.jsp , nameConfigPair[0]=roles, nameConfigPair[1]=admin,user
addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);
}
}
/**
* Splits the comma-delimited filter chain definition line into individual filter definition tokens.
*
* Example Input:
*
* foo, bar[baz], blah[x, y]
*
* Resulting Output:
*
* output[0] == foo
* output[1] == bar[baz]
* output[2] == blah[x, y]
*
* @param chainDefinition the comma-delimited filter chain definition.
* @return an array of filter definition tokens
* @since 1.2
* @see SHIRO-205
*/
protected String[] splitChainDefinition(String chainDefinition) {
return StringUtils.split(chainDefinition, StringUtils.DEFAULT_DELIMITER_CHAR, '[', ']', true, true);
}
protected String[] toNameConfigPair(String token) throws ConfigurationException {
try {
String[] pair = token.split("\\[", 2);
String name = StringUtils.clean(pair[0]);
if (name == null) {
throw new IllegalArgumentException("Filter name not found for filter chain definition token: " + token);
}
String config = null;
if (pair.length == 2) {
config = StringUtils.clean(pair[1]);
//if there was an open bracket, it assumed there is a closing bracket, so strip it too:
config = config.substring(0, config.length() - 1);
config = StringUtils.clean(config);
//backwards compatibility prior to implementing SHIRO-205:
//prior to SHIRO-205 being implemented, it was common for end-users to quote the config inside brackets
//if that config required commas. We need to strip those quotes to get to the interior quoted definition
//to ensure any existing quoted definitions still function for end users:
if (config != null && config.startsWith("\"") && config.endsWith("\"")) {
String stripped = config.substring(1, config.length() - 1);
stripped = StringUtils.clean(stripped);
//if the stripped value does not have any internal quotes, we can assume that the entire config was
//quoted and we can use the stripped value.
if (stripped != null && stripped.indexOf('"') == -1) {
config = stripped;
}
//else:
//the remaining config does have internal quotes, so we need to assume that each comma delimited
//pair might be quoted, in which case we need the leading and trailing quotes that we stripped
//So we ignore the stripped value.
}
}
return new String[]{name, config};
} catch (Exception e) {
String msg = "Unable to parse filter chain definition token: " + token;
throw new ConfigurationException(msg, e);
}
}
protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) {
Filter existing = getFilter(name);
if (existing == null || overwrite) {
if (filter instanceof Nameable) {
((Nameable) filter).setName(name);
}
if (init) {
initFilter(filter);
}
this.filters.put(name, filter);
}
}
public void addToChain(String chainName, String filterName) {
addToChain(chainName, filterName, null);
}
public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) {
if (!StringUtils.hasText(chainName)) {
throw new IllegalArgumentException("chainName cannot be null or empty.");
}
Filter filter = 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).");
}
applyChainConfig(chainName, filter, chainSpecificFilterConfig);
/ / filter 를 list 에 추가
/ / 데이터 구조 예: chainName = / index. jsp filers = roles, authc
NamedFilterList chain = ensureChain(chainName);
chain.add(filter);
}
protected void applyChainConfig(String chainName, Filter filter, String chainSpecificFilterConfig) {
if (log.isDebugEnabled()) {
log.debug("Attempting to apply path [" + chainName + "] to filter [" + filter + "] " +
"with config [" + chainSpecificFilterConfig + "]");
}
if (filter instanceof PathConfigProcessor) {
/ / 설정 정 보 를 filter 내부 applied Paths 데이터 구조 로 설정 합 니 다.
//chainName = /index.jsp chainSpecificFilterConfig = admin,user
((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig);
} else {
if (StringUtils.hasText(chainSpecificFilterConfig)) {
String msg = "chainSpecificFilterConfig was specified, but the underlying " +
"Filter instance is not an 'instanceof' " +
PathConfigProcessor.class.getName() + ". This is required if the filter is to accept " +
"chain-specific configuration.";
throw new ConfigurationException(msg);
}
}
}
protected NamedFilterList ensureChain(String chainName) {
NamedFilterList chain = getChain(chainName);
if (chain == null) {
chain = new SimpleNamedFilterList(chainName);
this.filterChains.put(chainName, chain);
}
return chain;
}
public NamedFilterList getChain(String chainName) {
return this.filterChains.get(chainName);
}
public boolean hasChains() {
return !CollectionUtils.isEmpty(this.filterChains);
}
public Set getChainNames() {
//noinspection unchecked
return this.filterChains != null ? this.filterChains.keySet() : Collections.EMPTY_SET;
}
/ / shiro 에이 전 트 를 만 드 는 FilterChain
public FilterChain proxy(FilterChain original, String chainName) {
NamedFilterList configured = getChain(chainName);
if (configured == null) {
String msg = "There is no configured chain under the name/key [" + chainName + "].";
throw new IllegalArgumentException(msg);
}
return configured.proxy(original);
}
/**
* Initializes the filter by calling filter.init( {@link #getFilterConfig() getFilterConfig()} );
.
*
* @param filter the filter to initialize with the {@code FilterConfig}.
*/
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 ConfigurationException(e);
}
}
/ / shiro 기본 filter 를 filter 에 추가 합 니 다.
protected void addDefaultFilters(boolean init) {
for (DefaultFilter defaultFilter : DefaultFilter.values()) {
addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
}
}
}
AbstractShiroFilter public abstract class AbstractShiroFilter extends OncePerRequestFilter {
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
throws ServletException, IOException {
Throwable t = null;
try {
final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
final Subject subject = createSubject(request, response);
//noinspection unchecked
subject.execute(new Callable() {
public Object call() throws Exception {
updateSessionLastAccessTime(request, response);
executeChain(request, response, chain);
return null;
}
});
} catch (ExecutionException ex) {
t = ex.getCause();
} catch (Throwable throwable) {
t = throwable;
}
if (t != null) {
if (t instanceof ServletException) {
throw (ServletException) t;
}
if (t instanceof IOException) {
throw (IOException) t;
}
//otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
String msg = "Filtered request failed.";
throw new ServletException(msg, t);
}
}
protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
FilterChain chain = origChain;
FilterChainResolver resolver = getFilterChainResolver();
if (resolver == null) {
log.debug("No FilterChainResolver configured. Returning original FilterChain.");
return origChain;
}
// shiro filter , shiro FilterChain
// ProxiedFilterChain shiro fitler origChain filter
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;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Shiro] Shiro 라벨 사용guest , , 。--> <shiro:guest> shiro:guest> <shiro:user> shiro:user> <--! authenticated , , Subject.login , 。...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.