博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊spring security的permitAll以及webIgnore
阅读量:6904 次
发布时间:2019-06-27

本文共 11821 字,大约阅读时间需要 39 分钟。

本文主要聊一下spring security的permitAll以及webIgnore的区别

permitAll配置实例

@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Override    public void configure(HttpSecurity http) throws Exception {        http                .authorizeRequests()                .antMatchers("/css/**", "/js/**","/fonts/**").permitAll()                .anyRequest().authenticated();    }}

web ignore配置实例

@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Override    public void configure(WebSecurity web) throws Exception {        web.ignoring().antMatchers("/css/**");        web.ignoring().antMatchers("/js/**");        web.ignoring().antMatchers("/fonts/**");    }}

二者区别

顾名思义,WebSecurity主要是配置跟web资源相关的,比如css、js、images等等,但是这个还不是本质的区别,关键的区别如下:

  • ingore是完全绕过了spring security的所有filter,相当于不走spring security
  • permitall没有绕过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 implements        InitializingBean {    //......    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;    }        //......}

这个filter的主要功能就是给没有登陆的用户,填充AnonymousAuthenticationToken到SecurityContextHolder的Authentication,后续依赖Authentication的代码可以统一处理。

FilterComparator

spring-security-config-4.1.4.RELEASE-sources.jar!/org/springframework/security/config/annotation/web/builders/FilterComparator.java

final class FilterComparator implements Comparator
, Serializable { private static final int STEP = 100; private Map
filterToOrder = new HashMap
(); 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); } //......}

这个类定义了spring security内置的filter的优先级,AnonymousAuthenticationFilter在倒数第五个执行,在FilterSecurityInterceptor这个类之前。

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. * 

* The SecurityMetadataSource required by this security interceptor is of * type {@link FilterInvocationSecurityMetadataSource}. *

* Refer to {@link AbstractSecurityInterceptor} for details on the workflow. *

* * @author Ben Alex * @author Rob Winch */public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { //......}

这个相当于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
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 authorization try { 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 user Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attributes); if (runAs == null) { if (debug) { logger.debug("RunAsManager did not change Authentication object"); } // no further work post-invocation return 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-invocation return new InterceptorStatusToken(origCtx, true, attributes, object); } } //......}

主要的逻辑在这个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        // that        if (logger.isDebugEnabled()) {            logger.debug("Successfully Authenticated: " + authentication);        }        SecurityContextHolder.getContext().setAuthentication(authentication);        return authentication;    }

这个方法判断authentication如果是已经校验过的,则返回;没有校验过的话,则调用authenticationManager进行鉴权。

而AnonymousAuthenticationFilter设置的authentication在这个时候就派上用场了

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
authorities) { super(authorities); if (principal == null || "".equals(principal)) { throw new IllegalArgumentException("principal cannot be null or empty"); } Assert.notEmpty(authorities, "authorities cannot be null or empty"); this.keyHash = keyHash; this.principal = principal; setAuthenticated(true); } //......}

它默认就是authenticated

小结

  • web ignore比较适合配置前端相关的静态资源,它是完全绕过spring security的所有filter的;
  • 而permitAll,会给没有登录的用户适配一个AnonymousAuthenticationToken,设置到SecurityContextHolder,方便后面的filter可以统一处理authentication。

doc

转载地址:http://cymdl.baihongyu.com/

你可能感兴趣的文章
Java程序员幽默爆笑锦集
查看>>
【勘误】第三章基本变量
查看>>
用友iuap入选2016世界互联网领先科技成果50强
查看>>
fastclick 源码注解及一些基础知识点
查看>>
CentOS Rsync服务端与Windows cwRsync客户端实现数据同步
查看>>
TAR包CLONE方式 安装11GR2 RAC数据库 (gril软件root.sh)
查看>>
热备份路由协议(HSRP)大型配置之详解
查看>>
gb2312编码文件转成utf8
查看>>
一次WinRoute后门攻防实况
查看>>
数据驱动业务决策的5个步骤
查看>>
上网个人信息如何不“裸奔” 10条信息安全建议
查看>>
JIRA的常用选项
查看>>
专访Facebook HipHop作者、阿里研究员赵海平:生物与计算机交织的独特人生
查看>>
监控视频须严加规范
查看>>
实例化需求的优点
查看>>
Linux管理常见错误的解决方法
查看>>
MySQL架构优化实战系列3:定时计划任务与表分区
查看>>
kafka - advertised.listeners and listeners
查看>>
Hadoop YARN学习监控JVM和实时监控Ganglia、Ambari(5)
查看>>
ECharts:免费,开源,超炫的可视化作品
查看>>