Spring Security生命周期简述

2023-05-16

Spring Security系列-Spring Security生命周期之起源_springsecurity生命周期_马各马它的博客-CSDN博客

 Spring Security系列-Spring Security生命周期之诞生_spring security 生命周期_马各马它的博客-CSDN博客

 Spring Security系列-Spring Security生命周期之出征_马各马它的博客-CSDN博客

一、起源 

1.1 配置

一个简单的WebSecurity配置,重载了三个config方法。分别配置了登录方式用户来源过滤特定url

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
                .httpBasic();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("admin")
                .password(passwordEncoder.encode("123456"))
                .authorities("admin");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**", "/favicon.ico");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

1.2 源头

1.2.1 SpringBootAutoconfigure

在使用SpringBoot时,会引用或者间接引用到包SpringBootAutoconfigure,这个包包含了一些常用的jar包的默认配置,如大家熟悉的server.port=8080。SpringSecurity的默认配置也会在SpringBootAutoconfigure包内。
SpringBootAutoconfigure包会加载一系列配置类,也包括SpringSecurity的配置类,如下图。

在这里插入图片描述

1.2.2 SecurityAutoConfiguration

其中有一个SecurityAutoConfiguration类,会在项目初始化是被加载。从下面的源代码可以看到SecurityAutoConfigurationimportWebSecurityEnablerConfiguration类。

@Configuration
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
		SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {
	...
}

1.2.3 WebSecurityEnablerConfiguration

WebSecurityEnablerConfiguration类加上了一个EnableWebSecurity注解

@Configuration
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {

}

1.2.4 EnableWebSecurity

EnableWebSecurity注解又importWebSecurityConfiguration

...
@Import({ WebSecurityConfiguration.class,
		SpringWebMvcImportSelector.class,
		OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
	...
}

1.2.5 WebSecurityConfiguration

WebSecurityConfiguration类中,有两个比较重要的步骤,如下。

@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
	...
	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		// 这里的webSecurityConfigurers就是我们在程序里的SpringSecurity配置
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
		return webSecurity.build();
	}
	...
	@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(
			ObjectPostProcessor<Object> objectPostProcessor,
			@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
			throws Exception {
		webSecurity = objectPostProcessor
			.postProcess(new WebSecurity(objectPostProcessor));
		...
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}
	...
}
  • 一个是setFilterChainProxySecurityConfigurer方法,负责初始化webSecurity和webSecurityConfigurers
  • webSecurity可以理解为顶层的WebSecurity配置,webSecurityConfigurers是通过beanFactory找到的所有继承WebSecurityConfigurer接口的类,也包括我们自定义的WebSecurity配置。
  • 实例化后的顶层webSecurity,再应用其它的webSecurityConfigurers配置。

接下来谈谈另一个重要的方法springSecurityFilterChain的Bean注入。这个springSecurityFilterChain会调用webSecurity的build方法,会根据自定义的WebSecurity配置,来建造相应的规则。

二、诞生

springSecurityFilterChain的形成,最终包含了4个filterChain。其中HttpSecurity生成的filterChainer,包含了多个filter。

主要介绍WebSecurity的规则是如何从自定义配置规则加入到整个SpringSecurity的认证链条的。

2.1 配置

WebSecurity配置

@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
                .httpBasic();
        // @formatter:on
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // @formatter:off
        auth
            .inMemoryAuthentication()
                .withUser("admin")
                .password(passwordEncoder.encode("123456"))
                .authorities("admin");
        // @formatter:on
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**", "/favicon.ico");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

2.2 配置方法

上面的三个config配置方法里,应用了许多配置项。
比如httpBasic()方法,从下面的源代码可以看出,它会实例化HttpBasicConfigurer类,并应用到HttpSecurity里。

public HttpBasicConfigurer<HttpSecurity> httpBasic() throws Exception {
	return getOrApply(new HttpBasicConfigurer<>());
}

又比如inMemoryAuthentication()方法。

public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
			throws Exception {
	return apply(new InMemoryUserDetailsManagerConfigurer<>());
}

无论是HttpBasicConfigurer还是InMemoryUserDetailsManagerConfigurer,都有同一个父类SecurityBuilder

2.3 builder设计模式

SecurityBuilder类是一个建造者类,只有一个build方法。

public interface SecurityBuilder<O> {
	O build() throws Exception;
}

SecurityBuilder有众多继承类,下面展示了其中的一部分。

在这里插入图片描述


还记得上一篇setFilterChainProxySecurityConfigurer方法创建的webSeurity对象,它也继承SecurityBuilder类。当webSeurity.build()后,就会引发它下面所有的SecurityBuild继承类的调用build方法,如上面说到的HttpBasicConfigurerInMemoryUserDetailsManagerConfigurer类。

2.4 webSecurity构建诞生

webSecurity.build()是怎么一步步应用自定义MyWebSecurityConfig 配置三个方法的。

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
	boolean hasConfigurers = webSecurityConfigurers != null
			&& !webSecurityConfigurers.isEmpty();
	if (!hasConfigurers) {
		WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
				.postProcess(new WebSecurityConfigurerAdapter() {
				});
		webSecurity.apply(adapter);
	}
	return webSecurity.build();
}

2.4.1 三个自定义配置

1) configure(AuthenticationManagerBuilder auth)

WebSecurity.build() ->
AbstractSecurityBuilder.build() ->
AbstractConfiguredSecurityBuilder.doBuild() ->
AbstractConfiguredSecurityBuilder.init()->
WebSecurityConfigurerAdapter.init(final WebSecurity web)->
WebSecurityConfigurerAdapter.getHttp()->
WebSecurityConfigurerAdapter.authenticationManager()->
自定义WebSecurityConfig->configure(AuthenticationManagerBuilder auth)

2) configure(HttpSecurity http)

然后是来到的configure(HttpSecurity http)方法。

WebSecurity.build() ->
AbstractSecurityBuilder.build() ->
AbstractConfiguredSecurityBuilder.doBuild() ->
AbstractConfiguredSecurityBuilder.init()->
WebSecurityConfigurerAdapter.init(final WebSecurity web)->
WebSecurityConfigurerAdapter.getHttp()->
自定义WebSecurityConfig->configure(HttpSecurity http)

3) configure(WebSecurity web)

最后是来到的configure(WebSecurity http)方法。

WebSecurity.build() ->
AbstractSecurityBuilder.build() ->
AbstractConfiguredSecurityBuilder.doBuild() ->
AbstractConfiguredSecurityBuilder.configure()->
自定义WebSecurityConfig->configure(WebSecurity web)

FilterChainProxy

在springSecurityFilterChain Bean的构建中,调用下面的performBuild()方法, 创建FilterChainProxy实例,并添加自定义配置到securityFilterChains中。ignoredRequests就是z自定义配置configure(WebSecurity web)方法中的web.ignoring().antMatchers("/css/", "/js/", “/favicon.ico”);而securityFilterChainBuilders就是自定义配置的configure(HttpSecurity http)。

protected Filter performBuild() throws Exception {
	int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
	List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
			chainSize);
	for (RequestMatcher ignoredRequest : ignoredRequests) {
		securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
	}
	for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
		securityFilterChains.add(securityFilterChainBuilder.build());
	}
	FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);

	Filter result = filterChainProxy;
	postBuildAction.run();
	return result;
}

2.4.2 ignoredRequest

下图可以清楚的看到3个ignoredRequest
在这里插入图片描述

2.4.3 securityFilterChain

securityFilterChain情况就比较复杂了,会合并我们自定义配置和默认配置

1) 默认配置

WebSecurity.build()方法被调用时,还有一段SpringSecurity设置默认配置的代码,如下

protected final HttpSecurity getHttp() throws Exception {
	...
	http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
			sharedObjects);
	if (!disableDefaults) {
		// @formatter:off
		http
			.csrf().and()                                       // 1
			.addFilter(new WebAsyncManagerIntegrationFilter())  // 2
			.exceptionHandling().and()                          // 3
			.headers().and()                                    // 4
			.sessionManagement().and()                          // 5
			.securityContext().and()                            // 6
			.requestCache().and()                               // 7
			.anonymous().and()                                  // 8
			.servletApi().and()                                 // 9
			.apply(new DefaultLoginPageConfigurer<>()).and()    //10
			.logout();                                          //11
		// @formatter:on
		...
	}
	configure(http);
	return http;
}

从上面SpringSecurity提供的默认配置可以看出,SpringSecurity默认地为我们添加了11个SecurityConfigurerFilter

2) SecurityConfigurer和Filter

以SpringSecurity提供的默认配置,csrf()方法为例。
首先,csrf()方法应用了一个CsrfConfigurer配置类,这个类继承自SecurityConfigurer

public final class HttpSecurity extends
	AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
	implements SecurityBuilder<DefaultSecurityFilterChain>,
	HttpSecurityBuilder<HttpSecurity> {
	...
	public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
		ApplicationContext context = getContext();
		return getOrApply(new CsrfConfigurer<>(context));
	}
	...
}		

接着,CsrfConfigurer实现了configure(Hhttp)方法,此方法会实例化一个CsrfFilter。

public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
		extends AbstractHttpConfigurer<CsrfConfigurer<H>, H> {
	...
	@Override
	public void configure(H http) throws Exception {
		CsrfFilter filter = new CsrfFilter(this.csrfTokenRepository);
		RequestMatcher requireCsrfProtectionMatcher = getRequireCsrfProtectionMatcher();
		if (requireCsrfProtectionMatcher != null) {
			filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher);
		}
		AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http);
		if (accessDeniedHandler != null) {
			filter.setAccessDeniedHandler(accessDeniedHandler);
		}
		LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
		if (logoutConfigurer != null) {
			logoutConfigurer
					.addLogoutHandler(new CsrfLogoutHandler(this.csrfTokenRepository));
		}
		SessionManagementConfigurer<H> sessionConfigurer = http
				.getConfigurer(SessionManagementConfigurer.class);
		if (sessionConfigurer != null) {
			sessionConfigurer.addSessionAuthenticationStrategy(
					new CsrfAuthenticationStrategy(this.csrfTokenRepository));
		}
		filter = postProcess(filter);
		http.addFilter(filter);
	}
	...
}

最终,这个Filter会被添加到到http,而这个http就是HttpSecurity类,是本篇在开头提到的getHttp()方法中实例出来的,同时也是我们的自定义配置类中可以看到的那个HttpSecurity http。

2.4.4 最终产物

springSecurityFilterChain是一个Bean。如果按照自定义配置,它会包括4个DefaultSecurityFilterChain

其中三个filterChain是自定义配置的web.ignoring().antMatchers("/css/", "/js/", “/favicon.ico”),另外一个是自定义配置的configure(HttpSecurity http)

HttpSecurity因为保留了SpringSecurity的默认配置,所以会有自定义配置之外的默认配置。

在这里插入图片描述

从上图可以看出,每一个HttpRequest都会经过4个FilterChain。

三、出征

主要介绍Spring Security是怎么对request请求进行拦截处理的。

3.1 入口

当客户端发送http request请求时,就会进入之前通过SpringSecurity创建的FilterChainProxydoFilter方法,再进入doFilterInternal方法。

public class FilterChainProxy extends GenericFilterBean {
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
		if (clearContext) {
			try {
				request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
				doFilterInternal(request, response, chain);
			}
			finally {
				SecurityContextHolder.clearContext();
				request.removeAttribute(FILTER_APPLIED);
			}
		}
		else {
			doFilterInternal(request, response, chain);
		}
	}
	
	private void doFilterInternal(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		FirewalledRequest fwRequest = firewall
				.getFirewalledRequest((HttpServletRequest) request);
		HttpServletResponse fwResponse = firewall
				.getFirewalledResponse((HttpServletResponse) response);

		List<Filter> filters = getFilters(fwRequest);

		if (filters == null || filters.size() == 0) {
			if (logger.isDebugEnabled()) {
				logger.debug(UrlUtils.buildRequestUrl(fwRequest)
						+ (filters == null ? " has no matching filters"
								: " has an empty filter list"));
			}

			fwRequest.reset();

			chain.doFilter(fwRequest, fwResponse);

			return;
		}

		VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
		vfc.doFilter(fwRequest, fwResponse);
	}
}

接着,进入VirtualFilterChain类的doFilter方法

private static class VirtualFilterChain implements FilterChain {
	@Override
	publicvoid doFilter(ServletRequest request, ServletResponse response)
			throws IOException, ServletException {
		if (currentPosition == size) {
			if (logger.isDebugEnabled()) {
				logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
						+ " reached end of additional filter chain; proceeding with original chain");
			}

			// Deactivate path stripping as we exit the security filter chain
			this.firewalledRequest.reset();

			originalChain.doFilter(request, response);
		}
		else {
			currentPosition++;

			Filter nextFilter = additionalFilters.get(currentPosition - 1);

			if (logger.isDebugEnabled()) {
				logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
						+ " at position " + currentPosition + " of " + size
						+ " in additional filter chain; firing Filter: '"
						+ nextFilter.getClass().getSimpleName() + "'");
			}

			nextFilter.doFilter(request, response, this);
		}
	}
}

上面的additionalFilters是生成的12个filters。上面的nextFilter就是在循环这12个filters,并在每一次循环中调用它们的doFilter方法。

3.2 GenericFilterBean

GenericFilterBean类是继承javax.servlet.Filter接口的。也就会在Tomcat接收到HttpRequest请求时,就调用Filter接口的doFilter方法。

public interface Filter {

    public default void init(FilterConfig filterConfig) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    public default void destroy() {}
}

3.3 自定义Filter

有兴趣的读者可以试一下下面的代码,当tomcat收到httpRequest的时候,就会触发doFilter方法。

@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("Do Filter");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

3.4 总结

SpringSecurity之所以能过滤,主要还是继承了javax.servlet.Filter接口。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Security生命周期简述 的相关文章

  • 算术左、右移位与逻辑左、右移位,右移一位和除二的区别、算术溢出

    当你通过搜索逻辑 xff0c 算术移位运算的时候 xff0c 一直寻找资料 xff0c 只不过可能你没有找到满意的回答 xff0c 看到这 xff0c 你大概率可以结束你的搜索过程了 这里先说一句很重要的话 xff1a 正数的原码 xff0
  • copy_{to, from}_user()的思考

    引言 我们对copy to from user 接口的使用应该是再熟悉不过吧 基本Linux书籍都会介绍它的作用 毕竟它是kernel space和user space沟通的桥梁 所有的数据交互都应该使用类似这种接口 所以 xff0c 我们
  • 60行C代码实现一个shell

    继 300来行代码带你实现一个能跑的最小Linux文件系统 之后 xff0c 我们来看看如何60行C代码实现一个shell xff01 在实现它之前 xff0c 先看看这样做的意义 美是有目共睹的 Unix之美 xff0c 稍微体会 xff
  • Linux内核如何私闯进程地址空间并修改进程内存

    进程地址空间的隔离 是现代操作系统的一个显著特征 这也是区别于 古代 操作系统 的显著特征 进程地址空间隔离意味着进程P1无法以随意的方式访问进程P2的内存 xff0c 除非这块内存被声明是共享的 这非常容易理解 xff0c 我举个例子 我
  • 宋宝华: Linux内核编程广泛使用的前向声明(Forward Declaration)

    前向声明 编程定律 先强调一点 xff1a 在一切可能的场景 xff0c 尽可能地使用前向声明 Forward Declaration 这符合信息隐蔽的原则 一个例子
  • 宋宝华: 几个人一起抢spinlock,到底谁先抢到?

    天问 公平在哪里 xff1f 几个人一起抢spinlock xff0c 到底谁先抢到呢 xff1f 这是一个问题 几个人一起去银行柜台 xff0c 到底谁先被服务到呢 xff1f 这是一个问题 闹地不好就要出问题 这个问题就是公平的问题 这
  • Linux free命令前后变化和available内存

    老版的free命令长成这个样子 xff1a 较新版本的Ubuntun CentOS等中的free命令是这个样子的 xff1a 主要的变化是buff cache被合并为一列 xff0c 并且增加了available这一列 available这
  • 朴英敏: 用crash工具分析Linux内核死锁的一次实战

    本文简介 xff1a 内核死锁问题一般是读写锁 rw semaphore 和互斥锁 mutex 引起的 xff0c 本文主要讲如何通过 ramdump 43 crash 工具 来分析这类死锁问题 作者简介 xff1a 朴英敏 xff0c 现
  • 宋宝华: 迭代螺旋法——关于Linux学习方法的血泪建议

    在下是一个码农 xff0c 也号称是一个老湿 xff0c 平生阅码农无数 吹牛的 经由大量的案例 xff0c 我能够理解了为什么很多码农学了很多年Linux xff0c 还是感觉没有掌握要领 xff0c 仍然内心崩溃 xff0c 最终对Li
  • (重磅原创)冬之焱: 谈谈Linux内核的栈回溯与妙用

    作者简介 xff1a 冬之焱 xff0c 杭州某公司linux内核工程师 xff0c 4年开发经验 xff0c 对运用linux内核的某些原理解决实际问题很感兴趣 版权声明 xff1a 本文最先发表于 34 Linux阅码场 34 微信公众
  • 开发技术-Error: Invalid or corrupt jarfile

    1 现状 xff1a 正常的发代码 xff0c 传到服务器后启动报错 奇了怪了 xff0c 怎么会报这个错 xff0c 也没改什么东西 比较了一下jar包 xff0c 发现服务器上的jar包小了 按理说通过xftp上传不会出现这个情况 2
  • CoreData的外键关联

    创建工程时勾选Use Core Data自动生成以下方法 AppDelegate h span class hljs preprocessor import span class hljs title lt UIKit UIKit h gt
  • 方向梯度直方图(Histogram Of Gradient)详解

    特征描述子 Feature Descriptor 特征描述子就是图像的表示 xff0c 抽取了有用的信息 xff0c 丢掉了不相关的信息 通常特征描述子会把一个w h 3 宽高3 xff0c 3个channel 的图像转换成一个长度为n的向
  • 第五周 D - 滑动窗口

    题目描述 ZJM 有一个长度为 n 的数列和一个大小为 k 的窗口 窗口可以在数列上来回移动 现在 ZJM 想知道在窗口从左往右滑的时候 xff0c 每次窗口内数的最大值和最小值分别是多少 例如 xff1a 数列是 1 3 1 3 5 3
  • Nextcloud基本使用方法

    下载和安装 Nextcloud 客户端 客户端可以在这里下载https nextcloud com install xff0c 您可以选择 Desktop 或者 Mobile 如果您是 Windows 用户 xff0c 可以直接点击这个链接
  • 一本通题解——1437:扩散

    题目链接 一本通OJ xff1a http ybt ssoier cn 8088 problem show php pid 61 1437 我的OJ xff1a http 47 110 135 197 problem php id 61 4
  • Ubuntu使用命令行配置WIFI

    事情起因 前面几天 xff0c 办公室切换网络 xff0c 导致老网络断线 今天办公地点调整了网络结构 xff0c 我的一个放在办公室拥有公网 IP 的 Ubuntu 18 04 服务器连接的内网 WIFI 发生变化 xff0c 需要用命令
  • 洛谷U149013题解

    洛谷U149013题解 前言题目解析逼死人的暴力正经的解析第一个程序第二个程序第三个程序第四个程序第五个程序第六个程序第七个程序第八个程序PS第九 十个程序 题解 结语 前言 今天我突发奇想 xff0c 在洛谷上创建了一道题目 xff0c
  • Codeforces游玩攻略

    Codeforces游玩攻略 1 简介2 网址3 使用1 主界面2 社区3 比赛名字颜色比赛种类比赛流程关于Codeforces赛制 xff1a 如何读懂排行榜Rating 4 题解 最后鸣谢 1 简介 Codeforces是全球最著名的在
  • MySQL连接不了本地服务器原因

    1 运行进入数据库报错 xff1a Could not acquire management access for administration RuntimeError Target host is configured as Windo

随机推荐

  • springboot、SpringCloud 常见版本版本介绍

    官方版本号 xff08 2023年5月6日 xff09 Spring Boot 版本说明 Spring Boot的版本号分析 xff1a Spring Boot的版本以数字表示 例如 xff1a Spring Boot 2 4 1 RELE
  • 热点账户及解决方案

    百度安全验证 我们经常听到一个概念 热点账户 xff0c 可能很多人不陌生什么是热点账户 xff0c 但是对如何解决热点账户问题并没有系统性的完整的思路 事物总是发展的 xff0c 事物所处的场景也是在不断变化的 xff0c 基于有限的经验
  • 笔记:vue 打包忽略部分文件检查。

    在需要 忽略的文件中加入 eslint disable 1 js 文件 首行直接加入 eslint disable 2 vue文件 script 中加入 eslint disable 3 配置文件进行配置 看大佬文章 vue中指定文件或文件
  • 公有云相关概念——region和AZ、VPC、安全组、公有云网络架构

    https www cnblogs com yunjisuanchengzhanglu p 16164376 html 一 region和az region xff08 区域 xff09 xff1a 一个region可以理解为一个大的独立的
  • Java四大引用详解:强引用、软引用、弱引用、虚引用

    Java四大引用详解 xff1a 强引用 软引用 弱引用 虚引用 java 软引用 mikechen的互联网架构的博客 CSDN博客 1 Java引用 从JDK 1 2版本开始 xff0c 对象的引用被划分为4种级别 xff0c 从而使程序
  • 延时队列方案选择及优缺点分析

    1 前言 https juejin cn post 6987233263660040206 在电商 支付等领域 xff0c 往往会有这样的场景 xff0c 用户下单后放弃支付了 xff0c 那这笔订单会在指定的时间段后进行关闭操作 订单关闭
  • 定时任务方案的正确选取

    在电商 支付等领域 xff0c 往往会有这样的场景 xff0c 用户下单后放弃支付了 xff0c 那这笔订单会在指定的时间段后进行关闭操作 xff0c 细心的你一定发现了像某宝 某东都有这样的逻辑 xff0c 而且时间很准确 xff0c 误
  • Redis教程总结

    Redis redis 时间轮 夜猫吃夜宵的博客 CSDN博客 一 Redis特性 快 为什么快 xff1f 基于内存操作 xff0c 操作不需要跟磁盘交互 本身就是k v结构 xff0c 类似hashMap xff0c 所以查询速度接近O
  • Shiro和Spring Security对比(3)

    https www cnblogs com hanease p 15906339 html 1 两个基本的概念 安全实体 xff1a 系统需要保护的具体对象数据权限 xff1a 系统相关的功能操作 xff0c 例如基本的CRUD 1 2 S
  • springboot整合邮箱功能一(实战)

    背景介绍 邮件发送其实是一个非常常见的需求 xff0c 用户注册 xff0c 找回密码 校验码等地方 如果使用短信还需缴费 这里发送者邮箱选用了163邮箱 1 pom xml文件的引用 lt xml version 61 34 1 0 34
  • Apache Camel简介

    Apache Camel简介 abinge89的博客 CSDN博客 1 什么是Camel 1 1 来源 Camel项目开始于2007年初 xff0c 虽然年轻 xff0c 但它已经是一个成熟的开源项目 xff0c 基于自由的Apache 2
  • springboot整合邮箱功能二(普通邮件, html邮件, thymleaf邮件)

    SpringBoot整合Email发送邮件 空 白 xfffd 的博客 CSDN博客 https www cnblogs com erlou96 p 16878192 html label1 5 1 准备工作 1 1 qq邮箱设置 本文默认
  • MySQL中Truncate用法详解

    MySQL中Truncate用法详解 Mysql 脚本之家 前言 xff1a 当我们想要清空某张表时 xff0c 往往会使用truncate语句 大多时候我们只关心能否满足需求 xff0c 而不去想这类语句的使用场景及注意事项 本篇文章主要
  • cesium 移除实体方法

    问题 xff1a cesium 移除entity 后 xff0c viewer entities values没有任何entity时 xff0c 图层上还会显示 解决方法 xff1a 无效方法 1 模拟代码 viewer entities
  • 时间轮算法在Netty和Kafka中的应用

    1 时间轮算法 时间轮算法 xff08 Time Wheel Algorithm xff09 是一种高效的定时器实现方式 xff0c 主要用于高并发下的定时任务调度 它利用了循环数组的思想 xff0c 将时间轴分成一个一个的时间槽 xff0
  • RabbitMQ事务概述

    RabbitMQ支持事务 transaction xff0c RabbitMQ中与事务机制有关的方法有三个 xff1a txSelect txCommit 以及txRollback xff08 1 xff09 txSelect用于将当前ch
  • 消息队列原理和应用场景简介

    一 消息队列的场景 异步处理流量控制服务解耦发布订阅高并发缓冲 1 1 异步处理 主要场景 xff1a 短信通知 终端状态推送 App推送 用户注册等 秒杀系统为例 更快速返回结果 xff1b 减少等待 xff0c 实现并发处理 xff0c
  • 消息队列-ZeroMQ

    一 吞吐量和延时性 二 ZeroMQ解决传统网络编程的问题 调用的socket接口较多 xff1b TCP是一对一的连接 xff1b 一对多 xff0c reactor模式编程需要关注很多socket细节问题 xff1b 不支持跨平台编程
  • SpringSecurity登录原理(源码级讲解

    SpringSecurity登录原理 xff08 源码级讲解 xff09 简书 一 简述 首先会进入UsernamePasswordAuthenticationFilter并且设置权限为null和是否授权为false xff0c 然后进入P
  • Spring Security生命周期简述

    Spring Security系列 Spring Security生命周期之起源 springsecurity生命周期 马各马它的博客 CSDN博客 Spring Security系列 Spring Security生命周期之诞生 spri