Spring Security问题解答报告

1,准备多个user,进行不同权限的演示
在重写UserDetailService中去修改不同的user,以此设置权限

2,configure(WebSecurity web)里配置了ignoring的资源,不受configure(HttpSecurity http)管理,尽量有依据

package org.springframework.security.config.annotation.web.configuration;

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.TYPE})
@Documented
@Import({
    
    WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, HttpSecurityConfiguration.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    
    
    boolean debug() default false;
}

debug作用

@Configuration
@EnableWebSecurity(debug = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
 public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
    
    
        this.webSecurity = (WebSecurity)objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
        if (this.debugEnabled != null) {
    
    
            this.webSecurity.debug(this.debugEnabled);
        }

        webSecurityConfigurers.sort(WebSecurityConfiguration.AnnotationAwareOrderComparator.INSTANCE);
        Integer previousOrder = null;
        Object previousConfig = null;

        Iterator var5;
        SecurityConfigurer config;
        for(var5 = webSecurityConfigurers.iterator(); var5.hasNext(); previousConfig = config) {
    
    
            config = (SecurityConfigurer)var5.next();
            Integer order = WebSecurityConfiguration.AnnotationAwareOrderComparator.lookupOrder(config);
            if (previousOrder != null && previousOrder.equals(order)) {
    
    
                throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
            }

            previousOrder = order;
        }

        var5 = webSecurityConfigurers.iterator();

        while(var5.hasNext()) {
    
    
        //将配置的每一个securityConfigurer列表传递给webSecurity
            config = (SecurityConfigurer)var5.next();
            this.webSecurity.apply(config);
        }

        this.webSecurityConfigurers = webSecurityConfigurers;
    }
@Bean(
        name = {
    
    "springSecurityFilterChain"}
    )
    public Filter springSecurityFilterChain() throws Exception {
    
    
        boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
        boolean hasFilterChain = !this.securityFilterChains.isEmpty();
        Assert.state(!hasConfigurers || !hasFilterChain, "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
        if (!hasConfigurers && !hasFilterChain) {
    
    
        //如果没有配置,则取默认配置
            WebSecurityConfigurerAdapter adapter = (WebSecurityConfigurerAdapter)this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {
    
    
            });
            this.webSecurity.apply(adapter);
        }

        Iterator var7 = this.securityFilterChains.iterator();

        while(true) {
    
    
            while(var7.hasNext()) {
    
    
                SecurityFilterChain securityFilterChain = (SecurityFilterChain)var7.next();
                this.webSecurity.addSecurityFilterChainBuilder(() -> {
    
    
                    return securityFilterChain;
                });
                Iterator var5 = securityFilterChain.getFilters().iterator();

                while(var5.hasNext()) {
    
    
                    Filter filter = (Filter)var5.next();
                    if (filter instanceof FilterSecurityInterceptor) {
    
    
                        this.webSecurity.securityInterceptor((FilterSecurityInterceptor)filter);
                        break;
                    }
                }
            }

            var7 = this.webSecurityCustomizers.iterator();

            while(var7.hasNext()) {
    
    
                WebSecurityCustomizer customizer = (WebSecurityCustomizer)var7.next();
                customizer.customize(this.webSecurity);
            }

//调用webSecurity的biud方法生成过滤器
            return (Filter)this.webSecurity.build();
        }
    }

    public final O build() throws Exception {
    
    
        if (this.building.compareAndSet(false, true)) {
    
    
        //TODO 
            this.object = this.doBuild();
            return this.object;
        } else {
    
    
            throw new AlreadyBuiltException("This object has already been built");
        }
    }
protected final O doBuild() throws Exception {
    
    
        synchronized(this.configurers) {
    
    
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;
            this.beforeInit();
            //初始化,将所有httpSecurity注册到websecurity中
            this.init();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;
            this.beforeConfigure();
            this.configure();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;
            //websecurity的performBuild
            O result = this.performBuild();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;
            return result;
        }
    }
protected Filter performBuild() throws Exception {
    
    
        Assert.state(!this.securityFilterChainBuilders.isEmpty(), () -> {
    
    
            return "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this is done by exposing a SecurityFilterChain bean or by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " + WebSecurity.class.getSimpleName() + ".addSecurityFilterChainBuilder directly";
        });
        int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
        List<SecurityFilterChain> securityFilterChains = new ArrayList(chainSize);
        Iterator var3 = this.ignoredRequests.iterator();

        while(var3.hasNext()) {
    
    
            RequestMatcher ignoredRequest = (RequestMatcher)var3.next();
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest, new Filter[0]));
        }

        var3 = this.securityFilterChainBuilders.iterator();

        while(var3.hasNext()) {
    
    
            SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder = (SecurityBuilder)var3.next();
            /来自我们自己的配置
            securityFilterChains.add(securityFilterChainBuilder.build());
        }

        FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
        if (this.httpFirewall != null) {
    
    
            filterChainProxy.setFirewall(this.httpFirewall);
        }

        if (this.requestRejectedHandler != null) {
    
    
            filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
        }

        filterChainProxy.afterPropertiesSet();
        Filter result = filterChainProxy;
        if (this.debugEnabled) {
    
    
            this.logger.warn("\n\n********************************************************************\n**********        Security debugging is enabled.       *************\n**********    This may include sensitive information.  *************\n**********      Do not use in a production system!     *************\n********************************************************************\n\n");
            result = new DebugFilter(filterChainProxy);
        }

        this.postBuildAction.run();
        return (Filter)result;
    }

3,loginProcessingUrl 和 TokenLoginFilter两种方式都可以配置登录以及实现token方案的演示

spring securiyt是由众多filters组合完成工作的,如果在loginProcessingUrl内去实现token的颁发,那就是要使用表单认证,我们需要自己自定义登录页面来处理我们的登录信息。

对此我们通常使用basic认证的方式

对于这两种方式的认证,简单来说

BASIC是利用HTTP头部进行认证,访问页面时会由浏览器弹框要求密码,这个是走HTTP协议层面的认证

FORM是基于页面,你需要自己实现一个登录页面,也就是示例中的/usercheck.jsp(名字你可以自己定),里面要有一个登录表单,表单的action和用户名 密码字段名都是框架定死的,然后你需要再实现一个servlet来处理这个表单的action,实现登录,实际上走的是session/cookie认证

4,login/logout的token持久化/清除方案

需要整合redis来做token的持久化处理,有效时长,刷新token以及token清除等,

扫描二维码关注公众号,回复: 13271949 查看本文章

5,SessionCreationPolicy.STATELESS的具体影响
security.sessions策略

6,把其它工程里关于SpringSecurity的功能,包括自定义注解等等,整合到single-security-jwt-model工程,形成一个专项工程。

找了spring security 的匿名注解的作用

7,TokenAuthenticationFilter对某些资源放行,跟Security configure里规则一致。

已做处理

猜你喜欢

转载自blog.csdn.net/m0_51945027/article/details/120053427