欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringSecurity在SpringBoot中的自動(dòng)裝配過(guò)程

 更新時(shí)間:2024年07月12日 10:57:33   作者:讓你三行代碼QAQ  
這篇文章主要介紹了SpringSecurity在SpringBoot中的自動(dòng)裝配過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

從SpringBoot的自動(dòng)裝配原理入手

找到META-INFO下的spring.factories文件

SpringSecurity作為Spring的親兒子,自然在spring-boot-autoconfigure下的spring.factories文件中配置了

org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\

UserDetailsServiceAutoConfiguration

@Configuration(
    proxyBeanMethods = false
)
//條件注解
@ConditionalOnClass({AuthenticationManager.class})
@ConditionalOnBean({ObjectPostProcessor.class})
//提供拓展,沒(méi)有提供以下三個(gè)實(shí)現(xiàn)類(lèi)才使用默認(rèn)的
@ConditionalOnMissingBean(
    value = {AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class},
    type = {"org.springframework.security.oauth2.jwt.JwtDecoder", "org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector"}
)
public class UserDetailsServiceAutoConfiguration {
    //密碼不加密表示
    private static final String NOOP_PASSWORD_PREFIX = "{noop}";
    private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern.compile("^\\{.+}.*$");
    private static final Log logger = LogFactory.getLog(UserDetailsServiceAutoConfiguration.class);

    public UserDetailsServiceAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        type = {"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository"}
    )
    @Lazy
    public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties, ObjectProvider<PasswordEncoder> passwordEncoder) {
        //讀取以spring.security開(kāi)頭的配置文件
        SecurityProperties.User user = properties.getUser();
        List<String> roles = user.getRoles();
        return new InMemoryUserDetailsManager(new UserDetails[]{User.withUsername(user.getName()).password(this.getOrDeducePassword(user, (PasswordEncoder)passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build()});
    }

    private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) {
        String password = user.getPassword();
        if (user.isPasswordGenerated()) {
            logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
        }

        return encoder == null && !PASSWORD_ALGORITHM_PATTERN.matcher(password).matches() ? "{noop}" + password : password;
    }
}
//標(biāo)記讀取配置文件夾信息
@ConfigurationProperties(
    prefix = "spring.security"
)
public class SecurityProperties {
    public static final int BASIC_AUTH_ORDER = 2147483642;
    public static final int IGNORED_ORDER = Integer.MIN_VALUE;
    public static final int DEFAULT_FILTER_ORDER = -100;
    private final Filter filter = new Filter();
    private User user = new User();

    public SecurityProperties() {
    }

    public User getUser() {
        return this.user;
    }

    public Filter getFilter() {
        return this.filter;
    }

    public static class User {
        //如果沒(méi)有配置,用戶(hù)名默認(rèn)user,密碼uuid
        private String name = "user";
        private String password = UUID.randomUUID().toString();
        private List<String> roles = new ArrayList();
        private boolean passwordGenerated = true;

        public User() {
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return this.password;
        }

        public void setPassword(String password) {
            if (StringUtils.hasLength(password)) {
                this.passwordGenerated = false;
                this.password = password;
            }
        }

        public List<String> getRoles() {
            return this.roles;
        }

        public void setRoles(List<String> roles) {
            this.roles = new ArrayList(roles);
        }

        public boolean isPasswordGenerated() {
            return this.passwordGenerated;
        }
    }

    public static class Filter {
        private int order = -100;
        private Set<DispatcherType> dispatcherTypes;

        public Filter() {
            this.dispatcherTypes = new HashSet(Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
        }

        public int getOrder() {
            return this.order;
        }

        public void setOrder(int order) {
            this.order = order;
        }

        public Set<DispatcherType> getDispatcherTypes() {
            return this.dispatcherTypes;
        }

        public void setDispatcherTypes(Set<DispatcherType> dispatcherTypes) {
            this.dispatcherTypes = dispatcherTypes;
        }
    }
}

SecurityFilterAutoConfiguration

約定大于配置,這里的內(nèi)容就相當(dāng)于在web.xml配置文件中配置springSecurityFilterChain的過(guò)程由spring自動(dòng)實(shí)現(xiàn).spring自動(dòng)注入DelegatingFilterProxy對(duì)象,這樣就可以將security中的過(guò)濾器切到spring中,在請(qǐng)求的時(shí)候會(huì)被DelegatingFilterProxyRegistrationBean攔截,然后去執(zhí)行security中的過(guò)濾器鏈。

@Configuration(
    proxyBeanMethods = false
)
//web項(xiàng)目才加載
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@EnableConfigurationProperties({SecurityProperties.class})
@ConditionalOnClass({AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class})
//SecurityAutoConfiguration之后執(zhí)行
@AutoConfigureAfter({SecurityAutoConfiguration.class})
public class SecurityFilterAutoConfiguration {
    //名字
    private static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

    public SecurityFilterAutoConfiguration() {
    }

    /**
     * 創(chuàng)建DelegatingFilterProxyRegistrationBean對(duì)象注入到spring容器中
     * @param securityProperties
     * @return
     */
    @Bean
    @ConditionalOnBean(
        name = {"springSecurityFilterChain"}
    )
    public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(SecurityProperties securityProperties) {
        //創(chuàng)建DelegatingFilterProxy對(duì)象
        DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean("springSecurityFilterChain", new ServletRegistrationBean[0]);
        registration.setOrder(securityProperties.getFilter().getOrder());
        registration.setDispatcherTypes(this.getDispatcherTypes(securityProperties));
        return registration;
    }

    private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
        return securityProperties.getFilter().getDispatcherTypes() == null ? null : (EnumSet)securityProperties.getFilter().getDispatcherTypes().stream().map((type) -> {
            return DispatcherType.valueOf(type.name());
        }).collect(Collectors.toCollection(() -> {
            return EnumSet.noneOf(DispatcherType.class);
        }));
    }
}

創(chuàng)建DelegatingFilterProxy的過(guò)程實(shí)際是通過(guò)ServletContextInitializer接口實(shí)現(xiàn)的,有一個(gè)方法onStartup,有一個(gè)實(shí)現(xiàn)類(lèi)RegistrationBean

public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
    private static final Log logger = LogFactory.getLog(RegistrationBean.class);
    private int order = Integer.MAX_VALUE;
    private boolean enabled = true;

    public RegistrationBean() {
    }

    public final void onStartup(ServletContext servletContext) throws ServletException {
        String description = this.getDescription();
        if (!this.isEnabled()) {
            logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
        } else {
            //注冊(cè)
            this.register(description, servletContext);
        }
    }

    protected abstract String getDescription();

    protected abstract void register(String description, ServletContext servletContext);

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public int getOrder() {
        return this.order;
    }
}

注冊(cè)邏輯在父類(lèi)DynamicRegistrationBean中

public abstract class DynamicRegistrationBean<D extends Registration.Dynamic> extends RegistrationBean {
    private static final Log logger = LogFactory.getLog(RegistrationBean.class);
    private String name;
    private boolean asyncSupported = true;
    private Map<String, String> initParameters = new LinkedHashMap();

    public DynamicRegistrationBean() {
    }

    public void setName(String name) {
        Assert.hasLength(name, "Name must not be empty");
        this.name = name;
    }

    public void setAsyncSupported(boolean asyncSupported) {
        this.asyncSupported = asyncSupported;
    }

    public boolean isAsyncSupported() {
        return this.asyncSupported;
    }

    public void setInitParameters(Map<String, String> initParameters) {
        Assert.notNull(initParameters, "InitParameters must not be null");
        this.initParameters = new LinkedHashMap(initParameters);
    }

    public Map<String, String> getInitParameters() {
        return this.initParameters;
    }

    public void addInitParameter(String name, String value) {
        Assert.notNull(name, "Name must not be null");
        this.initParameters.put(name, value);
    }

    protected final void register(String description, ServletContext servletContext) {
        //生成DelegatingFilterProxy對(duì)象
        D registration = this.addRegistration(description, servletContext);
        if (registration == null) {
            logger.info(StringUtils.capitalize(description) + " was not registered (possibly already registered?)");
        } else {
            //在其父類(lèi)AbstractFilterRegistrationBean中配置攔截/*請(qǐng)求
            this.configure(registration);
        }
    }

    protected abstract D addRegistration(String description, ServletContext servletContext);

    protected void configure(D registration) {
        registration.setAsyncSupported(this.asyncSupported);
        if (!this.initParameters.isEmpty()) {
            registration.setInitParameters(this.initParameters);
        }

    }

    protected final String getOrDeduceName(Object value) {
        return this.name != null ? this.name : Conventions.getVariableName(value);
    }
}

跟蹤代碼發(fā)現(xiàn)實(shí)際調(diào)用的了DelegatingFilterProxyRegistrationBean的getFilter方法

public class DelegatingFilterProxyRegistrationBean extends AbstractFilterRegistrationBean<DelegatingFilterProxy> implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    private final String targetBeanName;

    public DelegatingFilterProxyRegistrationBean(String targetBeanName, ServletRegistrationBean<?>... servletRegistrationBeans) {
        super(servletRegistrationBeans);
        Assert.hasLength(targetBeanName, "TargetBeanName must not be null or empty");
        this.targetBeanName = targetBeanName;
        this.setName(targetBeanName);
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    protected String getTargetBeanName() {
        return this.targetBeanName;
    }
    
    //創(chuàng)建DelegatingFilterProxy實(shí)例對(duì)象
    public DelegatingFilterProxy getFilter() {
        return new DelegatingFilterProxy(this.targetBeanName, this.getWebApplicationContext()) {
            protected void initFilterBean() throws ServletException {
            }
        };
    }

    private WebApplicationContext getWebApplicationContext() {
        Assert.notNull(this.applicationContext, "ApplicationContext be injected");
        Assert.isInstanceOf(WebApplicationContext.class, this.applicationContext);
        return (WebApplicationContext)this.applicationContext;
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis-plus查詢(xún)無(wú)數(shù)據(jù)問(wèn)題及解決

    mybatis-plus查詢(xún)無(wú)數(shù)據(jù)問(wèn)題及解決

    這篇文章主要介紹了mybatis-plus查詢(xún)無(wú)數(shù)據(jù)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • RocketMQ消息丟失的場(chǎng)景以及解決方案

    RocketMQ消息丟失的場(chǎng)景以及解決方案

    Apache RocketMQ是企業(yè)級(jí)的消息中間件,以其高性能和高可靠性而廣泛應(yīng)用,但是,消息丟失的問(wèn)題在實(shí)踐中仍然存在,本文將探討此問(wèn)題并提供解決方案,需要的朋友可以參考下
    2023-11-11
  • Spring?Boot中的微信支付全過(guò)程(小程序)

    Spring?Boot中的微信支付全過(guò)程(小程序)

    微信支付是企業(yè)級(jí)項(xiàng)目中經(jīng)常使用到的功能,作為后端開(kāi)發(fā)人員,完整地掌握該技術(shù)是十分有必要的。今天通過(guò)本文給大家介紹Spring?Boot中的微信支付全過(guò)程,感興趣的朋友一起看看吧
    2022-05-05
  • JAVA socket.io注解原理及用法圖解

    JAVA socket.io注解原理及用法圖解

    這篇文章主要介紹了JAVA socket.io注解原理及用法圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • springboot結(jié)合JWT實(shí)現(xiàn)單點(diǎn)登錄的示例

    springboot結(jié)合JWT實(shí)現(xiàn)單點(diǎn)登錄的示例

    本文主要介紹了springboot結(jié)合JWT實(shí)現(xiàn)單點(diǎn)登錄的示例,包括生成Token、驗(yàn)證Token及使用Redis存儲(chǔ)Token,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-01-01
  • SpringBoot自定義注解實(shí)現(xiàn)Token校驗(yàn)的方法

    SpringBoot自定義注解實(shí)現(xiàn)Token校驗(yàn)的方法

    這篇文章主要介紹了SpringBoot自定義注解實(shí)現(xiàn)Token校驗(yàn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Maven pom.xml scope屬性的使用

    Maven pom.xml scope屬性的使用

    在Maven中,scope屬性用于定義依賴(lài)關(guān)系在不同生命周期階段的行為,影響依賴(lài)在構(gòu)建過(guò)程中的下載和使用,以及是否傳遞給其他項(xiàng)目,常見(jiàn)的scope值包括compile、provided、runtime和test等
    2025-01-01
  • SpringBoot對(duì)PDF進(jìn)行模板內(nèi)容填充與電子簽名合并詳解

    SpringBoot對(duì)PDF進(jìn)行模板內(nèi)容填充與電子簽名合并詳解

    這篇文章主要為大家詳細(xì)介紹了SpringBoot對(duì)PDF進(jìn)行模板內(nèi)容填充與電子簽名合并的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考下
    2023-12-12
  • Java樹(shù)形結(jié)構(gòu)遞歸查詢(xún)方式

    Java樹(shù)形結(jié)構(gòu)遞歸查詢(xún)方式

    文章介紹了Java中實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)遞歸查詢(xún)的方法,首先找出所有的根節(jié)點(diǎn),然后通過(guò)循環(huán)遍歷根節(jié)點(diǎn),找到每個(gè)根節(jié)點(diǎn)的子節(jié)點(diǎn),最終構(gòu)建完整的樹(shù)形結(jié)構(gòu),這是一種有效的遞歸查詢(xún)思路,適用于需要層次化展示數(shù)據(jù)的場(chǎng)景
    2024-12-12
  • Intellij IDEA 添加jar包的三種方式(小結(jié))

    Intellij IDEA 添加jar包的三種方式(小結(jié))

    這篇文章主要介紹了Intellij IDEA 添加jar包的三種方式(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08

最新評(píng)論