聊聊spring security的permitAll以及webIgnore
序
本文主要聊一下spring security的permitAll以及webIgnore的區(qū)別
permitAll配置實(shí)例
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/css/**", "/js/**","/fonts/**").permitAll().anyRequest().authenticated();} }復(fù)制代碼web ignore配置實(shí)例
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/css/**");web.ignoring().antMatchers("/js/**");web.ignoring().antMatchers("/fonts/**");} }復(fù)制代碼二者區(qū)別
顧名思義,WebSecurity主要是配置跟web資源相關(guān)的,比如css、js、images等等,但是這個(gè)還不是本質(zhì)的區(qū)別,關(guān)鍵的區(qū)別如下:
- ingore是完全繞過(guò)了spring security的所有filter,相當(dāng)于不走spring security
- permitall沒(méi)有繞過(guò)spring security,其中包含了登錄的以及匿名的。
AnonymousAuthenticationFilter
spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java
/*** Detects if there is no {@code Authentication} object in the* {@code SecurityContextHolder}, and populates it with one if needed.** @author Ben Alex* @author Luke Taylor*/ public class AnonymousAuthenticationFilter extends GenericFilterBean implementsInitializingBean {//......public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {if (SecurityContextHolder.getContext().getAuthentication() == null) {SecurityContextHolder.getContext().setAuthentication(createAuthentication((HttpServletRequest) req));if (logger.isDebugEnabled()) {logger.debug("Populated SecurityContextHolder with anonymous token: '"+ SecurityContextHolder.getContext().getAuthentication() + "'");}}else {if (logger.isDebugEnabled()) {logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '"+ SecurityContextHolder.getContext().getAuthentication() + "'");}}chain.doFilter(req, res);}protected Authentication createAuthentication(HttpServletRequest request) {AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key,principal, authorities);auth.setDetails(authenticationDetailsSource.buildDetails(request));return auth;}//...... }復(fù)制代碼這個(gè)filter的主要功能就是給沒(méi)有登陸的用戶,填充AnonymousAuthenticationToken到SecurityContextHolder的Authentication,后續(xù)依賴Authentication的代碼可以統(tǒng)一處理。
FilterComparator
spring-security-config-4.1.4.RELEASE-sources.jar!/org/springframework/security/config/annotation/web/builders/FilterComparator.java
final class FilterComparator implements Comparator<Filter>, Serializable {private static final int STEP = 100;private Map<String, Integer> filterToOrder = new HashMap<String, Integer>();FilterComparator() {int order = 100;put(ChannelProcessingFilter.class, order);order += STEP;put(ConcurrentSessionFilter.class, order);order += STEP;put(WebAsyncManagerIntegrationFilter.class, order);order += STEP;put(SecurityContextPersistenceFilter.class, order);order += STEP;put(HeaderWriterFilter.class, order);order += STEP;put(CorsFilter.class, order);order += STEP;put(CsrfFilter.class, order);order += STEP;put(LogoutFilter.class, order);order += STEP;put(X509AuthenticationFilter.class, order);order += STEP;put(AbstractPreAuthenticatedProcessingFilter.class, order);order += STEP;filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",order);order += STEP;put(UsernamePasswordAuthenticationFilter.class, order);order += STEP;put(ConcurrentSessionFilter.class, order);order += STEP;filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order);order += STEP;put(DefaultLoginPageGeneratingFilter.class, order);order += STEP;put(ConcurrentSessionFilter.class, order);order += STEP;put(DigestAuthenticationFilter.class, order);order += STEP;put(BasicAuthenticationFilter.class, order);order += STEP;put(RequestCacheAwareFilter.class, order);order += STEP;put(SecurityContextHolderAwareRequestFilter.class, order);order += STEP;put(JaasApiIntegrationFilter.class, order);order += STEP;put(RememberMeAuthenticationFilter.class, order);order += STEP;put(AnonymousAuthenticationFilter.class, order);order += STEP;put(SessionManagementFilter.class, order);order += STEP;put(ExceptionTranslationFilter.class, order);order += STEP;put(FilterSecurityInterceptor.class, order);order += STEP;put(SwitchUserFilter.class, order);}//...... }復(fù)制代碼這個(gè)類定義了spring security內(nèi)置的filter的優(yōu)先級(jí),AnonymousAuthenticationFilter在倒數(shù)第五個(gè)執(zhí)行,在FilterSecurityInterceptor這個(gè)類之前。
FilterSecurityInterceptor
spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/access/intercept/FilterSecurityInterceptor.java
/*** Performs security handling of HTTP resources via a filter implementation.* <p>* The <code>SecurityMetadataSource</code> required by this security interceptor is of* type {@link FilterInvocationSecurityMetadataSource}.* <p>* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.* </p>** @author Ben Alex* @author Rob Winch*/ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implementsFilter {//...... }復(fù)制代碼這個(gè)相當(dāng)于spring security的核心處理類了,它繼承抽象類AbstractSecurityInterceptor
spring-security-core-4.2.3.RELEASE-sources.jar!/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java
public abstract class AbstractSecurityInterceptor implements InitializingBean,ApplicationEventPublisherAware, MessageSourceAware {//......protected InterceptorStatusToken beforeInvocation(Object object) {Assert.notNull(object, "Object was null");final boolean debug = logger.isDebugEnabled();if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {throw new IllegalArgumentException("Security invocation attempted for object "+ object.getClass().getName()+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "+ getSecureObjectClass());}Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object);if (attributes == null || attributes.isEmpty()) {if (rejectPublicInvocations) {throw new IllegalArgumentException("Secure object invocation "+ object+ " was denied as public invocations are not allowed via this interceptor. "+ "This indicates a configuration error because the "+ "rejectPublicInvocations property is set to 'true'");}if (debug) {logger.debug("Public object - authentication not attempted");}publishEvent(new PublicInvocationEvent(object));return null; // no further work post-invocation}if (debug) {logger.debug("Secure object: " + object + "; Attributes: " + attributes);}if (SecurityContextHolder.getContext().getAuthentication() == null) {credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound","An Authentication object was not found in the SecurityContext"),object, attributes);}Authentication authenticated = authenticateIfRequired();// Attempt authorizationtry {this.accessDecisionManager.decide(authenticated, object, attributes);}catch (AccessDeniedException accessDeniedException) {publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated,accessDeniedException));throw accessDeniedException;}if (debug) {logger.debug("Authorization successful");}if (publishAuthorizationSuccess) {publishEvent(new AuthorizedEvent(object, attributes, authenticated));}// Attempt to run as a different userAuthentication runAs = this.runAsManager.buildRunAs(authenticated, object,attributes);if (runAs == null) {if (debug) {logger.debug("RunAsManager did not change Authentication object");}// no further work post-invocationreturn new InterceptorStatusToken(SecurityContextHolder.getContext(), false,attributes, object);}else {if (debug) {logger.debug("Switching to RunAs Authentication: " + runAs);}SecurityContext origCtx = SecurityContextHolder.getContext();SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());SecurityContextHolder.getContext().setAuthentication(runAs);// need to revert to token.Authenticated post-invocationreturn new InterceptorStatusToken(origCtx, true, attributes, object);}}//...... }復(fù)制代碼主要的邏輯在這個(gè)beforeInvocation方法,它就依賴了authentication
private Authentication authenticateIfRequired() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication.isAuthenticated() && !alwaysReauthenticate) {if (logger.isDebugEnabled()) {logger.debug("Previously Authenticated: " + authentication);}return authentication;}authentication = authenticationManager.authenticate(authentication);// We don't authenticated.setAuthentication(true), because each provider should do// thatif (logger.isDebugEnabled()) {logger.debug("Successfully Authenticated: " + authentication);}SecurityContextHolder.getContext().setAuthentication(authentication);return authentication;}復(fù)制代碼這個(gè)方法判斷authentication如果是已經(jīng)校驗(yàn)過(guò)的,則返回;沒(méi)有校驗(yàn)過(guò)的話,則調(diào)用authenticationManager進(jìn)行鑒權(quán)。
而AnonymousAuthenticationFilter設(shè)置的authentication在這個(gè)時(shí)候就派上用場(chǎng)了
spring-security-core-4.2.3.RELEASE-sources.jar!/org/springframework/security/authentication/AnonymousAuthenticationToken.java
```
public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements
Serializable {
private AnonymousAuthenticationToken(Integer keyHash, Object principal,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
}
```
它默認(rèn)就是authenticated
小結(jié)
- web ignore比較適合配置前端相關(guān)的靜態(tài)資源,它是完全繞過(guò)spring security的所有filter的;
- 而permitAll,會(huì)給沒(méi)有登錄的用戶適配一個(gè)AnonymousAuthenticationToken,設(shè)置到SecurityContextHolder,方便后面的filter可以統(tǒng)一處理authentication。
doc
- spring security 的幾個(gè)細(xì)節(jié)
- Spring Security – security none, filters none, access permitAll
- Spring Security permitAll() not allowing anonymous access
- Difference between access=“permitAll” and filters=“none”?
總結(jié)
以上是生活随笔為你收集整理的聊聊spring security的permitAll以及webIgnore的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Delphi常见各类编译错误信息-中英对
- 下一篇: shell脚本中的坑