Spring Security Oauth2.0认证授权
基本概念
认证: 用户认证就是判断一个用户的身份是否合法的过程 ,用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹认证等方式。
会话:用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中。会话就是系统为了保持当前用户的登录状态所提供的机制,常见的有基于session方式、基于token方式等。
授权:授权是用户认证通过后根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。授权可简单理解为Who对What(which)进行How操作,
Who,即主体( Subject), 主体一般是指用户,也可以是程序,需要访问系统中的资源。
What,即资源( Resource), 如系统菜单、页面、按钮、代码方法、系统商品信息、系统订单信息等。系统菜单、页面、按钮、代码方法都属于 系统功能资源,对于web系统每个功能资源通常对应一个URL ;系统商品信息系统订单信息都属于 实体资源(数据资源), 实体资源由资源类型和资源实例组成,比如商品信息为资源类型,商品编号为001的商品为资源实例。
How ,权限/许可( Permission), 规定了用户对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个代码方法的调用权限、编号为001的用户的修改权限等,通过权限可知用户对哪些资源都有哪些操作许可。
授权的数据模型

资源和权限可以合并一起

RBAC
基于角色的访问控制 if (主体.hasRole()){}
基于资源的访问控制 if(主体.hasPermission()){}
Spring Boot Security
对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源,通过Filter实现

2.1 结构原理
初始化Spring Security时,初始化一个类型为org.springframework.security.web.FilterChainProxy的过滤器,
外部的请求会经过此类。FilterChainProxy是一个代理,真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,同时这些Filter作为Bean被Spring管理,它们是Spring Security核心,并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和 决策管理器(AccessDecisionManager)进行处理

spring Security功能的实现主要是由一系列过滤器链相互配合完成。

2.2 认证过程
1. 用户提交用户名、密码被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
2. 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
3. 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除) Authentication 实例。
4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过
SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。

AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,
它的实现类为ProviderManager。
而Spring Security支持多种认证方式,因此ProviderManager维护着一个List<AuthenticationProvider> 列表,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成。不同的认证方式使用不同的AuthenticationProvider。如使用用户名密码登录时,使用DaoAuthenticationProvide
DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终AuthenticationProvider将UserDetails填充至Authentication。
2.3 密码处理
Spring Security提供了很多内置的PasswordEncoder,能够开箱即用,使用某种PasswordEncoder只需要进行如
下声明即可

常见的密码编码器有
NoOpPasswordEncoder、BCryptPasswordEncoder、Pbkdf2PasswordEncode、SCryptPasswordEncoder
2.4 授权过程
已认证用户访问受保护的web资源将被SecurityFilterChain中的 FilterSecurityInterceptor 的子类拦截。
FilterSecurityInterceptor会从 SecurityMetadataSource 的子类DefaultFilterInvocationSecurityMetadataSource 获取要访问当前资源所需要的权限Collection<ConfigAttribute>
SecurityMetadataSource其实就是读取“安全拦截机制”
FilterSecurityInterceptor会调用 AccessDecisionManager 进行授权决策,若决策通过,则允许访问资源,否则将禁止访问。此处会从安全上下文中获取用户:Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 再进行比对和判断。

decide接口就是用来鉴定当前用户是否有访问对应受保护资源的权限。
authentication:要访问资源的访问者的身份
object:要访问的受保护资源,web请求对应FilterInvocation
confifigAttributes:是受保护资源的访问策略,通过SecurityMetadataSource获取。

Spring Security内置了三个基于投票的AccessDecisionManager实现类
AffirmativeBased 只要有一个赞成票,则表示同意用户访问
ConsensusBased:赞成票多余反对票,则表示同意用户访问
UnanimousBased:只要有一个反对票,则表示反对用户访问
spring security为防止CSRF(Cross-site request forgery跨站请求伪造)的发生,限制了除了get以外的大多数方法,
解决方法1:
屏蔽CSRF控制,即spring security不再限制CSRF。httpSecurity.csrf().disable()
解决方法2:
表单添加隐藏域: <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
2.5 实际应用
用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保存在会话中。spring security提供会话管理,认证通过后将身份信息放入SecurityContextHolder上下文,SecurityContext与当前线程进行绑定,方便获取用户身份。
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
2.5.1 会话控制
Spring Security会为每个登录成功的用户会新建一个Session
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
session超时、session失效后,通过Spring Security 设置跳转的路径。
httpSecurity.sessionManagement()
.expiredUrl("/login‐view?error=EXPIRED_SESSION")
.invalidSessionUrl("/login‐view?error=INVALID_SESSION");
session退出
httpSecurity.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login‐view?logout")
.logoutSuccessHandler(logoutSuccessHandler)
.addLogoutHandler(logoutHandler)
.invalidateHttpSession(true)
定制的 LogoutSuccessHandler ,实现用户退出成功时的处理。如果指定了这个选项那么logoutSuccessUrl() 的设置被忽略;
添加一个 LogoutHandler ,用于实现用户退出时的清理工作.默认 SecurityContextLogoutHandler 会被添加为最后一个 LogoutHandler;
指定是否在退出时让 HttpSession 无效。 默认设置为 true。
2.5.2 web授权
使用 http.authorizeRequests() 对web资源进行授权保护
httpSecurity
.authorizeRequests()
.antMatchers("/r/r1").hasAuthority("p1") (
.antMatchers("/r/r2").hasAuthority("p2")
.antMatchers("/r/r3").access("hasAuthority('p1') and hasAuthority('p2')")
.antMatchers("/r/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
保护URL常用的方法有:
authenticated() 保护URL,需要用户登录
permitAll() 指定URL无需保护,一般应用与静态资源文件
hasRole(String role) 限制单个角色访问,角色将被增加 “ROLE_” .所以”ADMIN” 将和 “ROLE_ADMIN”进行比较.
hasAuthority(String authority) 限制单个权限访问
hasAnyRole(String… roles)允许多个角色访问.
hasAnyAuthority(String… authorities) 允许多个权限访问.
access(String attribute) 该方法使用 SpEL表达式, 所以可以创建复杂的限制.
hasIpAddress(String ipaddressExpression) 限制IP地址或子网
2.5.3.方法授权
以在任何 @Configuration 实例上使用 @EnableGlobalMethodSecurity 注释来启用基于注解的安全性。
@PreAuthorize,@PostAuthorize, @Secured三类注解作用域服务层方法上,限制访问的访问
例如:
匿名访问
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
@PreAuthorize("isAnonymous()")
方法可匿名访问,底层使用WebExpressionVoter投票器
@PreAuthorize
@PreAuthorize("hasAuthority('p_transfer') and hasAuthority('p_read_account')")
同时拥有p_transfer和p_read_account权限才能访问,底层使用WebExpressionVoter投票器
另外,还有注解@PostAuthorize
分布式系统认证方案
软件的架构由单体结构演变为分布式架构,具有分布式架构的系统叫分布式系统,分布式系统的运行通常依赖网络,它将单体结构的系统分为若干服务,服务之间通过网络交互来完成用户的业务处理,当前流行的微服务架构就是分布式系统架构。

3.1 分布式认证需求
分布式系统的每个服务都会有认证、授权的需求,考虑分布式系统共享性的特点,需要由独立的认证服务处理系统认证授权的请求;考虑分布式系统开放性的特点,不仅对系统内部服务提供认证,对第三方系统也要提供认证。分布式认证的需求总结如下:
统一认证授权
提供独立的认证服务,统一处理认证授权。无论是不同类型的用户,还是不同种类的客户端(web端,H5、APP),均采用一致的认证、权限、会话机制,实现统一认证授权。要实现统一则认证方式必须可扩展,支持各种认证需求,比如:用户名密码认证、短信验证码、二维码、人脸识别等认证方式,并可以非常灵活的切换。
应用接入认证
应提供扩展和开放能力,提供安全的系统对接机制,并可开放部分API给接入第三方使用,一方应用(内部系统服务)和三方应用(第三方应用)均采用统一机制接入。
3.2 选型分析
3.2.1 基于Session认证
每个应用服务都需要在session中存储用户身份信息,通常的做法有下面几种:
Session复制:多台应用服务器之间同步session,使session保持一致,对外透明。
Session黏贴:当用户访问集群中某台服务器后,强制指定后续所有请求均落到此机器上。
Session集中存储:将Session存入分布式缓存中,所有服务器应用实例统一从分布式缓存中存取Session。

基于session认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高。但是,session机制方式基于cookie,在复杂多样的移动客户端上不能有效的使用,并且无法跨域,另外随着系统的扩展需提高session的复制、黏贴及存储的容错性。
3.2.2 基于Token认证
基于token的认证方式,服务端不用存储认证数据,易维护扩展性强, 客户端可以把token 存在任意地方,并且可以实现web和app统一认证机制。其缺点也很明显,token由于自包含信息,因此一般数据量较大,而且每次请求都需要传递,因此比较占带宽。另外,token的签名验签操作也会给cpu带来额外的处理负担。

3.2.3 技术方案
根据 选型分析,采用token认证,它的优点是:
适合统一认证的机制,客户端、一方应用、三方应用都遵循一致的认证机制。
token认证方式对第三方应用接入更适合,因为它更开放,可使用当前有流行的开放协议Oauth2.0、JWT等。
一般情况服务端无需存储会话信息,减轻了服务端的压力。

3.3 Oauth2.0
OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。例如,第三方登录,用户 授权 电商网站 访问 用户存储在微信平台的用户信息

OAauth2.0包括以下角色:
客户端
本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,比如:Android客户端、Web客户端(浏览器端)、微信客户端等。
资源拥有者
通常为用户,也可以是应用程序,即该资源的拥有者。
资源服务器
存储资源的服务器,例如微信平台用户信息资源。
服务提供商会给准入的接入方一个身份,用于接入时的凭据:
client_id:客户端标识
client_secret:客户端秘钥
授权服务器(也称认证服务器)
用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌,作为客户端访问资源服务器的凭据。例如:微信认证服务器。
授权服务器对OAuth2.0中的两个角色进行认证授权,分别是资源拥有者、客户端
Spring Cloud Security OAuth2
Spring-Security-OAuth2是对OAuth2的一种实现,并且跟Spring Security相辅相成,与SpringCloud体系的集成也非常便利。其服务实现包括两个服务:
认证授权服务 (Authorization Server)
应包含对接入端以及登入用户的合法性进行验证并颁发token等功能,对令牌的请求端点由 Spring MVC 控制器进行实现,下面是配置一个认证服务必须要实现的endpoints:
AuthorizationEndpoint 服务于认证请求。默认 URL:
/oauth/authorize 。
TokenEndpoint 服务于访问令牌的请求。默认 URL:
/oauth/token 。
资源服务 (Resource Server),
应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务:
OAuth2AuthenticationProcessingFilter用来对请求给出的身份令牌解析鉴权。
4.1 授权服务器配置
可以使用
@Configuration
@EnableAuthorizationServer
注解并继承AuthorizationServerConfifigurerAdapter来配置OAuth2.0 授权服务器。
AuthorizationServerConfifigurerAdapter要求配置
ClientDetailsServiceConfifigurer:用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化
AuthorizationServerEndpointsConfifigurer:用来配置令牌(token)的访问端点和令牌服务(tokenservices)。
AuthorizationServerSecurityConfifigurer:用来配置令牌访问端点的安全约束
4.1.1 客户端详情
ClientDetailsServiceConfifigurer能够使用内存或者JDBC来实现客户端详情,ClientDetailsService负责查找ClientDetails,而ClientDetails有几个重要的属性

客户端详情(Client Details)能够在应用程序运行的时候进行更新,可以通过访问底层的存储服务(例如将客户端详情存储在一个关系数据库的表中,就可以使用 JdbcClientDetailsService)或者通过实现
ClientRegistrationService接口(同时你也可以实现 ClientDetailsService 接口)来管理。
此次客户端详情读取数据库的配置:

4.1.2 令牌管理服务
AuthorizationServerTokenServices 接口定义了一些操作可以对令牌进行一些必要的管理,这个接口的实现,则需要继承 DefaultTokenServices,里面包含了一些有用实现,你可以使用它来修改令牌的格式和令牌的存储,其持久化令牌委托一个 TokenStore 接口来实现,TokenStore 这个接口有一个默认的实现,它就是 InMemoryTokenStore。
InMemoryTokenStore:
这个版本的实现是被默认采用的,它可以完美的工作在单服务器上(即访问并发量压力不大的情况下,并且它在失败的时候不会进行备份),大多数的项目都可以使用这个版本的实现来进行尝试,可以在开发的时候使用它来进行管理,因为不会被保存到磁盘中,更易于调试。
JdbcTokenStore:
这是一个基于JDBC的实现版本,令牌会被保存进关系型数据库。使用这个版本的实现时,你可以在不同的服务器之间共享令牌信息,使用这个版本的时候需要把"spring-jdbc"这个依赖加入到classpath。
JwtTokenStore
这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势),但是它有一个缺点,那就是撤销一个已经授权令牌将会非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)。另外一个缺点就是这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息。JwtTokenStore 不会保存任何数据,但是它在转换令牌值以及授权信息方面与 DefaultTokenServices 所扮演的角色是一样的。



4.1.3 令牌访问端点
4.1.3.1 认证管理器
AuthorizationServerEndpointsConfifigurer通过设定以下属性决定支持的授权类型(Grant Types):
authenticationManager
认证管理器,选择了资源所有者密码(password)授权类型的时候,请设置这个属性注入一个 AuthenticationManager 对象。
userDetailsService
设置了这个属性,需要有一个 UserDetailsService 接口的实现
authorizationCodeServices:
用来设置授权码服务(即 AuthorizationCodeServices 的实例对象),主要用于 "authorization_code" 授权码类型模式。
implicitGrantServic
这个属性用于设置隐式授权模式,用来管理隐式授权模式的状态。
tokenGranter:
授权将会交由自己来完全掌控,并且会忽略掉上面的这几个属性,这个属性一般是用作拓展用途

4.1.3.2 令牌访问点
框架的默认URL访问链接如下列表
/oauth/authorize:授权端点。
/oauth/token:令牌端点。
/oauth/confifirm_access:用户确认授权提交端点。
/oauth/error:授权服务错误信息端点。
/oauth/check_token:用于资源服务访问的令牌解析端点。
/oauth/token_key:提供公有密匙的端点,如果你使用JWT令牌的话。
AuthorizationServerEndpointsConfifigurer 这个配置对象有一个叫做 pathMapping() 的方法用来配置端点URL链接,它有两个参数:
第一个参数:String 类型的,这个端点URL的默认链接。
第二个参数:String 类型的,你要进行替代的URL链接。

4.1.4 令牌访问端点安全约束
AuthorizationServerSecurityConfigurer: :用来配置令牌端点(Token Endpoint)的安全约束

4.1.5 WEB安全配置

4.1.6 授权类型
4.1.6.1授权码模式
资源拥有者打开客户端,客户端要求资源拥有者给予授权,它将浏览器被重定向到授权服务器,重定向时会附加客户端的身份信息
/uaa/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
浏览器出现向授权服务器授权页面,之后用户同意授权
授权服务器将授权码(AuthorizationCode)经浏览器发送给client
客户端拿着授权码向授权服务器索要访问access_token
/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=5PgfcD&redirect_uri=http://www.baidu.com
授权服务器返回令牌(access_token)
参数列表如下
client_id:客户端准入标识。
response_type:授权码模式固定为code。
scope:客户端权限。
client_secret:客户端秘钥。
grant_type:授权类型,填写authorization_code,表示授权码模式
code:授权码,就是刚刚获取的授权码,注意:授权码只使用一次就无效了,需要重新申请。
redirect_uri:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。
4.1.6.2 简化模式
资源拥有者打开客户端,客户端要求资源拥有者给予授权,它将浏览器被重定向到授权服务器,重定向时会附加客户端的身份信息
/uaa/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
浏览器出现向授权服务器授权页面,之后用户同意授权
授权服务器将授权码将令牌(access_token)以Hash的形式存放在重定向uri的fargment中发送给浏览器。fragment 主要是用来标识 URI 所标识资源里的某个资源,在 URI 的末尾通过 (#)作为 fragment 的开头,其中 # 不属于 fragment 的值。
4.1.6.3 密码模式
资源拥有者将用户名、密码发送给客户端
客户端拿着资源拥有者的用户名、密码向授权服务器请求令牌(access_token)
/uaa/oauth/token?
client_id=c1&client_secret=secret&grant_type=password&username=shangsan&password=123
授权服务器将令牌(access_token)发送给client
4.1.6.4 客户端模式
客户端向授权服务器发送自己的身份信息,并请求令牌(access_token)
确认客户端身份无误后,将令牌(access_token)发送给client
/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials
4.2资源服务器配置
@Configuration
@EnableResourceServer
public class ResouceServerConfig extends ResourceServerConfigurerAdapter
@EnableResourceServer 注解自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链
ResourceServerSecurityConfifigurer中主要包括:
tokenServices:ResourceServerTokenServices 类的实例,用来实现令牌服务。
tokenStore:TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选
resourceId:这个资源服务的ID,这个属性是可选的,但是推荐设置并在授权服务中进行验证。
其他的拓展属性例如 tokenExtractor 令牌提取器用来提取请求中的令牌。
HttpSecurity配置这个与Spring Security类似:
请求匹配器,用来设置需要进行保护的资源路径,默认的情况下是保护资源服务的全部路径。
通过http.authorizeRequests()来设置受保护资源的访问规则
其他的自定义权限保护规则通过 HttpSecurity 来进行配置。

RemoteTokenServices 资源服务器通过 HTTP 请求来解码令牌,每次都请求授权服务器端点 /oauth/check_token

此处使用JWT校验令牌

配置安全拦截机制

@EnableResourceServer 注解自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链,此过滤器作用,主要是用来解析网关传过来的用户信息字符串,并存入安全上下文中

4.3 网关
网关整合 OAuth2.0作为OAuth2.0的资源服务器角色,实现接入客户端权限拦截、令牌解析并转发当前登录用户信息(jsonToken)给微服务


public class AuthFilter extends ZuulFilter
校验客户端token,验证接入客户端权限,并解析后明文token,转发请求到微服务

相关文章:

Spring Security Oauth2.0认证授权
基本概念认证: 用户认证就是判断一个用户的身份是否合法的过程 ,用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机…...

安卓小游戏:贪吃蛇
安卓小游戏:贪吃蛇 前言 这个是通过自定义View实现小游戏的第二篇,实际上第一篇做起来麻烦点,后面的基本就是照葫芦画瓢了,只要设计下游戏逻辑就行了,技术上不难,想法比较重要。 需求 贪吃蛇࿰…...

CUDA中的图内存节点
CUDA中的图内存节点 文章目录CUDA中的图内存节点1. 简介2. 支持的架构和版本3. API基础知识3.1. 图节点 APIs3.2. 流捕获3.3. 在分配图之外访问和释放图内存3.4. cudaGraphInstantiateFlagAutoFreeOnLaunch4. 优化内存复用4.1. 解决图中的重用问题4.2. 物理内存管理和共享5. 性…...

你真的看好低代码开发吗?
低代码开发前景如何,大家真的看好低代码开发吗?之前有过很多关于低代码的内容,这篇就来梳理下国内外低代码开发平台发展现状及前景。 01、国外低代码开发平台现状 2014年,研究机构Forrester Research发表的报告中提到“面向客户…...

一篇带你MySQL运维
1. 日志 1.1 错误日志 错误日志是 MySQL 中 重要的日志之一,它记录了当 mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,建议首先查看此日志。 该日志是默认开启的&…...

《嵌入式 – GD32开发实战指南》第22章 SPI
开发环境: MDK:Keil 5.30 开发板:GD32F207I-EVAL MCU:GD32F207IK 22.1 SPI简介 SPI,是Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的…...

一个优质软件测试工程师的简历应该有的样子(答应我一定要收藏起来)
个人简历 基本信息 姓 名:xxx 性 别: 女 年 龄:24 现住 地址: 深圳 测试 经验:3年 学 历:本科 联系 电话:18xxxxxxxx 邮 箱:xxxxl163.com 求职意向 应聘岗位:软件…...

C++ 浅谈之 STL Deque
C 浅谈之 STL Deque HELLO,各位博友好,我是阿呆 🙈🙈🙈 这里是 C 浅谈系列,收录在专栏 C 语言中 😜😜😜 本系列阿呆将记录一些 C 语言重要的语法特性 🏃&a…...

Koa2-项目中的基本应用
文章目录安装配置koa2配置nodemon,热更新我们的项目中间件什么是中间件👻洋葱模型路由中间件连接数据库 - mysql后端允许跨域处理请求getpostputdelete后续会继续更新安装配置koa2 👻安装 koa2 npm i koa2 -s👻在package.json 配置,当然是在…...
Flask入门(2):配置
目录2.Flask配置2.1 直接写入主脚本2.2 系统环境变量2.3 单独的配置文件2.4 多个配置类2.5 Flask内置配置2.Flask配置 我们都知道,Flask应用程序肯定是需要各种各样的配置。来满足我们不同的需求的,这样可以使我们的应用程序更加灵活。比如可以根据需要…...

Linux--fork
一、fork入门知识 fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。可以简单地说fork()的作用就是创建一…...

计算机组成原理(一)
1.了解计算机硬件的发展和软件的发展历程; 硬件: 电子管时代(1946-1959):电子管、声汞延迟线、磁鼓 晶体管时代(1959-1964):晶体管、磁芯 中、小规模集成电路时代&#…...
【SpringBoot】实现Async异步任务
1. 环境准备 在 Spring Boot 入口类上配置 EnableAsync 注解开启异步处理。 创建任务抽象类 AbstractTask,并分别配置三个任务方法 doTaskOne(),doTaskTwo(),doTaskThree()。 public abstract class AbstractTask {private static Random r…...

Node =>Express学习
1.Express 能做什么 能快速构建web网站的服务器 或 Api接口的服务期 Web网站服务器,专门对外提供Web网页资源的服务器Api接口服务器:专门对外提供API接口的服务器 2.安装 在项目所处的目录中,运行以下命令,简装到项目中了 npm …...

QT基础入门【布局篇】消除控件之间的间隔
一、相关参数 layoutLeftMargin: layout内的布局距离边框左端的距离。 layoutTopMargin: layout内的布局距离边框顶端的距离。 layoutRightMargin: layout内的布局距离边框右端的距离。 layoutBottomMargin: layout内的布局距离边框底端的距离。 layoutHorizontalSpacing: layo…...

vue脚手架 element-ui spring boot 实现图片上传阿里云 并保存到数据库
一.阿里云 注册登陆就不讲了,登陆进去后如下操作 1. 进入对象存储OSS 创建一个新的Bucket 随后点击新建的bucket 2.去访问RAM 前往RAM控制台 3.去创建用户 4.创建密匙 5.随后返回RAM控制台 给用户增加权限,文件上传所需权限,需要带含有…...

【FPGA】Verilog:组合电路 | 3—8译码器 | 编码器 | 74LS148
前言:本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例:编码/译码器的应用 功能特性: 采用 Xilinx Artix-7 XC7A35T芯片 配置方式:USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度 存储器&…...

GLP-1类药物研发进展-销售数据-上市药品前景分析
据一项2021 年的报告发现,当 GLP-1 类似物用于治疗 2 型糖尿病时,全因死亡率降低了 12%,它们不仅降糖效果显著,同时还兼具减重、降压、改善血脂谱等作用。近几年,随着GLP-1R激动剂类药物市场规模不断增长,美…...
C++远程监控系统接收端- RevPlayMDIChildWnd.cpp
void CRevPlayWnd::InitMultiSock() { int RevBuf; int status; BOOL bFlag; CString ErrMsg; SOCKADDR_IN stLocalAddr; SOCKADDR_IN stDestAddr; SOCKET hNewSock; int RevLensizeof(RevBuf); //创建一个IP组播套接字 MultiSock W…...

QT之OpenGL深度测试
QT之OpenGL深度测试1. 深度测试概述1. 1 提前深度测试1.2 深度测试相关函数2. 深度测试精度2.1 深度冲突3. Demo4. 参考1. 深度测试概述 在OpenGL中深度测试(Depth Testing)是关闭的,此时在渲染图形时会产生一种现象后渲染的会把最先渲染的遮挡住。而在启用深度测试…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...