- 浏览: 192297 次
- 性别:
- 来自: 南京
文章分类
最新评论
前言:
当用spring security时,我们会用到各种各样的filter,在接下来的章节中我们我们将着重讨论几个核心的Filter,本节将讨论FilterSecurityInterceptor这个filter。
和这个类相关的对象如下图所示
一、FilterSecurityInterceptor功能和属性
1.FilterSecurityInterceptor的主要职责是处理http资源的安全性。从上面的关系图中,可以知道这个类中主要有以下属性
上面的属性会在下面三个主要的方法中被使用到
1.1.beforeInvocation方法
这个方法是最主要的方法,我们的权限判断逻辑主要在这个方法里进行,主要执行下面几步逻辑
另外说下FilterSecurityInterceptor的securityMetadataSource属性实际定义的是SecurityMetadataSource的子类FilterInvocationSecurityMetadataSource,这个接口是一个标记接口,里面没有方法,仅仅说明用这个接口的实现类知道传入的安全对象是一个FilterInvocation,并能从里面获取到request,
1.2.finallyInvocation方法
这个方法的逻辑比较简单,如果配置了RunAsManager,在前一步执行过程中我们会把Authentication对象替换掉,这个方法里就是把原始的Authentication给替换回来,如果没有Authentication没有被替换过,这个方法什么都不做。
1.3.afterInvocation
如果配置了AfterInvocationManager属性,在这个方法中会调用AfterInvocationManager.decide方法,这个主要是在一些特定场合下,我们需要修改安全认证的返回结果,例如在MethodSecurityInterceptor认证中,如果我们方法放回的是一个list,我们想把这个list中的某些数据过滤掉则会配置这个属性。在FilterSecurityInterceptor认证中,不会有返回值,所以这个属性正常不会被配置。
二、在spring boot环境下,采用Java config机制这个filter是如何追加到servlet中对我们的请求进行拦截的呢
在前面的章节(spring-security(十六)Filter配置原理)中,我们知道spring 安全相关的Filter是在WebSecurity的build方法中调用HttpSecurity的build来将追加到HttpSecurity中filter列表排好序后构建成SecurityFilterChain,再把所有的SecurityFilterChain追加到FilterChainProxy中,最后通过DelegatingFilterProxy注册到ServletContext中的,下面我们主要来看下这个类是如何追加到HttpSecuriy的filter列表中的,以及对应的主要属性是如何配置的。
1. 从我们的配置入口WebSecurityConfigurerAdapter类开始,首先是在WebSecurityConfigurerAdapter类的configure(HttpSecurity http)方法中会调用http.authorizeRequests()方法,在实际应用中我们会重写configure方法来自定义安全策略,但是一定会执行http.authorizeRequests()方法。下面看下这个方法
两个功能
2. WebSecurity在构建HttpSecurity时,会调用HttpSecurity的build方法,这个方法会先执行HttpSecurity的configure()方法,就是依次调用configurers属性中各个SecurityConfigurer的configure方法
3. 下面来看下ExpressionUrlAuthorizationConfigurer的configure方法,代码逻辑在父类AbstractInterceptUrlConfigurer中
在这个方法里面主要执行了下面三件事
这样就可以明确看出我们的FilterSecurityInterceptor被加入到了httpsecurity的filter列表中了,下面我们看下这个filter中几个主要属性是怎么设置的
首先是创建metadataSource的方法createMetadataSource,具体代码逻辑就在ExpressionUrlAuthorizationConfigurer中
主要是通过REGISTRY.createRequestMap来获取,这个REGISTRY就是我们前面看到的Httpsecurity.authorizeRequests返回的值,我们设置的安全规则主要就是通过这个类设置的,例如下面的代码段
通过antMatchers方法,会创建一个AuthorizedUrl,里面的requestMatchers是AntPathRequestMatcher列表,对应的匹配路径是/admin/**,之后调用他的hasRole方法,具体代码在AuthorizedUrl类中,如下
看到将我们设置好的路径匹配模式和对应的属性追加到了REGISTRY中,通过hasRole方法我们传入的是ADMIN字符串,是如何转换成ConfigAttribute呢,在上面的access方法中,我们看到是调用了SecurityConfig.createList(attribute)来做的
就是简单的将我们的字符串包装成ConfigAttribute 的一个具体实现类SecurityConfig。
这样通过
这样一句配资,我们最终在ExpressionUrlAuthorizationConfigurer的REGISTRY属性中追加了如下一条匹配模式是/admin/**,对应的attributes是包含ADMIN字符串的SecurityConfig。
现在我们再回过头在看下创建SecurityMetadataSource的REGISTRY.createRequestMap方法
很明显,就是将我们追加到里面的UrlMapping转换成Map返回,最终构造出了一个ExpressionBasedFilterInvocationSecurityMetadataSource返回出去,在这个类的构造函数中,还会做一次转换把配置属性的类型转换成WebExpressionConfigAttribute(在鉴权类中用的Voter类是WebExpressionVoter,对应的属性是WebExpressionConfigAttribute,下面会提到)。
这样SecurityMetadataSource的创建过程就结束了。当一个请求进入FilterSecurityInterceptor中,就利用SecurityMetadataSource中的requestMap对路径进行匹配,找到第一个匹配的配置项后就获取到了对应的ConfigAttribute列表,传入到具体的鉴权类中进行处理。
4. 下面看下AuthenticationManager和AccessDecisionManager如何设置
可以看到authenticationManager直接用的是通过AuthenticationManagerBuilder构建出来后存在Httpsecurity中的对象,AccessDecisionManager是通过getAccessDecisionManager这个方法获取的
在默认情况下,spring 给我们组装了一个AffirmativeBased类,用的Voter类通过getDecisionVoters获取,具体在ExpressionUrlAuthorizationConfigurer类中
因为用的是WebExpressionVoter,所以在之前创建SecurityMetadataSource时需要做一次转换。
各种AccessDecisionManager实现类的具体意义我们在讨论鉴权的时候再具体分析。
这样我们的FilterSecurityInterceptor就完全组装好了,并且也作为Filter追加到了servlet中,可以对我们的资源进行保护了。
当用spring security时,我们会用到各种各样的filter,在接下来的章节中我们我们将着重讨论几个核心的Filter,本节将讨论FilterSecurityInterceptor这个filter。
和这个类相关的对象如下图所示
一、FilterSecurityInterceptor功能和属性
1.FilterSecurityInterceptor的主要职责是处理http资源的安全性。从上面的关系图中,可以知道这个类中主要有以下属性
- AuthenticationManager-认证
- AccessDecisionManager-鉴权
- SecurityMetadataSource-获取属性列表
- RunAsManager-替换认证用户
- AfterInvocationManager-鉴权完成后续处理
上面的属性会在下面三个主要的方法中被使用到
- beforeInvocation
- finallyInvocation
- afterInvocation
1.1.beforeInvocation方法
这个方法是最主要的方法,我们的权限判断逻辑主要在这个方法里进行,主要执行下面几步逻辑
- 调用SecurityMetadataSource(实际执行时spring boot为我们装配的实例是ExpressionBasedFilterInvocationSecurityMetadataSource,可以通过FilterSecurityInterceptor.setSecurityMetadataSource方法修改)来获取匹配当前请求的ConfigAttribute列表,如果获取的列表为null并且rejectPublicInvocations属性配置的是true(不允许存在不受保护的调用),则直接抛出异常,否则鉴权处理结束,如果不为null,执行下一步,因为ExpressionBasedFilterInvocationSecurityMetadataSource在获取当前request相匹配的ConfigAttribute列表时是按照定义的顺序来查找的,一旦找到匹配的就直接返回,所有越具体的匹配规则应配置的越靠前
- 判断SecurityContextHolder中是否包含Authentication对象,如果没有,就是说程序执行到这个鉴权的filter了却还没有认证过,直接抛出AuthenticationException异常,如果有Authentication,执行下一步
- 判断alwaysReauthenticate的值,如果设置成true,即所有请求在鉴权前都需要重新认证,则会调用AuthenticationManager(实际执行时是ProviderManager实例)的authenticate方法,进行具体的再认证过程,并把认证结果放入SecurityContextHolder中。
- 接着调用AccessDecisionManager(默认情况下是AffirmativeBased实例)decide方法,传入Authentication对象、当前的安全对象、以及对应的ConfigAttribute列表开始鉴权,在鉴权过程中如果发生AccessDeniedException,发布鉴权异常事件并抛出异常
- 如果配置了RunAsManager(在有些特殊场合下,如我们的业务层的某个方法中需要访问外部系统,需要我们提供一个不同的证书,我们可以配置这个RunAsManager,将当前认证过的用户替换成外部系统需要的认证者,之后spring security会自动把安全证书传递到外部系统中,默认是NullRunAsManager即不需要转换用户),则对用户进行转换,将转换后的用户存入SecurityContextHolder中,放回一个InterceptorStatusToken,否则直接返回InterceptorStatusToken对象
另外说下FilterSecurityInterceptor的securityMetadataSource属性实际定义的是SecurityMetadataSource的子类FilterInvocationSecurityMetadataSource,这个接口是一个标记接口,里面没有方法,仅仅说明用这个接口的实现类知道传入的安全对象是一个FilterInvocation,并能从里面获取到request,
public Collection<ConfigAttribute> getAttributes(Object object) { final HttpServletRequest request = ((FilterInvocation) object).getRequest(); for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry:requestMap .entrySet()) { if (entry.getKey().matches(request)) { return entry.getValue(); } } return null; }
1.2.finallyInvocation方法
这个方法的逻辑比较简单,如果配置了RunAsManager,在前一步执行过程中我们会把Authentication对象替换掉,这个方法里就是把原始的Authentication给替换回来,如果没有Authentication没有被替换过,这个方法什么都不做。
1.3.afterInvocation
如果配置了AfterInvocationManager属性,在这个方法中会调用AfterInvocationManager.decide方法,这个主要是在一些特定场合下,我们需要修改安全认证的返回结果,例如在MethodSecurityInterceptor认证中,如果我们方法放回的是一个list,我们想把这个list中的某些数据过滤掉则会配置这个属性。在FilterSecurityInterceptor认证中,不会有返回值,所以这个属性正常不会被配置。
二、在spring boot环境下,采用Java config机制这个filter是如何追加到servlet中对我们的请求进行拦截的呢
在前面的章节(spring-security(十六)Filter配置原理)中,我们知道spring 安全相关的Filter是在WebSecurity的build方法中调用HttpSecurity的build来将追加到HttpSecurity中filter列表排好序后构建成SecurityFilterChain,再把所有的SecurityFilterChain追加到FilterChainProxy中,最后通过DelegatingFilterProxy注册到ServletContext中的,下面我们主要来看下这个类是如何追加到HttpSecuriy的filter列表中的,以及对应的主要属性是如何配置的。
1. 从我们的配置入口WebSecurityConfigurerAdapter类开始,首先是在WebSecurityConfigurerAdapter类的configure(HttpSecurity http)方法中会调用http.authorizeRequests()方法,在实际应用中我们会重写configure方法来自定义安全策略,但是一定会执行http.authorizeRequests()方法。下面看下这个方法
public ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests()throws Exception { ApplicationContext context = getContext(); return getOrApply(new ExpressionUrlAuthorizationConfigurer<HttpSecurity>(context)).getRegistry(); }
两个功能
- 创建了一个实现了SecurityConfigurer接口的配置类ExpressionUrlAuthorizationConfigurer,通过调用getOrApply方法最终追加到HttpSecurity的configurers属性中
- 通过 ExpressionUrlAuthorizationConfigurer的getRegistry返回了一个ExpressionInterceptUrlRegistry对象
2. WebSecurity在构建HttpSecurity时,会调用HttpSecurity的build方法,这个方法会先执行HttpSecurity的configure()方法,就是依次调用configurers属性中各个SecurityConfigurer的configure方法
private void configure() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> configurer : configurers) { configurer.configure((B) this); } } private Collection<SecurityConfigurer<O, B>> getConfigurers() { List<SecurityConfigurer<O, B>> result = new ArrayList<SecurityConfigurer<O, B>>(); for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) { result.addAll(configs); } return result; }
3. 下面来看下ExpressionUrlAuthorizationConfigurer的configure方法,代码逻辑在父类AbstractInterceptUrlConfigurer中
@Override public void configure(H http) throws Exception { FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http); if (metadataSource == null) { return; } FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor( http, metadataSource, http.getSharedObject(AuthenticationManager.class)); if (filterSecurityInterceptorOncePerRequest != null) { securityInterceptor .setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); } securityInterceptor = postProcess(securityInterceptor); http.addFilter(securityInterceptor); http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); }
在这个方法里面主要执行了下面三件事
- 通过调用createMetadataSource方法创建了FilterInvocationSecurityMetadataSource对象
- 调用createFilterSecurityInterceptor创建了FilterSecurityInterceptor
- 通过http.addFilter方法追加到了HttpSecurity的filter列表中
这样就可以明确看出我们的FilterSecurityInterceptor被加入到了httpsecurity的filter列表中了,下面我们看下这个filter中几个主要属性是怎么设置的
首先是创建metadataSource的方法createMetadataSource,具体代码逻辑就在ExpressionUrlAuthorizationConfigurer中
@Override final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource( H http) { LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = REGISTRY.createRequestMap(); if (requestMap.isEmpty()) { throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); } return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); }
主要是通过REGISTRY.createRequestMap来获取,这个REGISTRY就是我们前面看到的Httpsecurity.authorizeRequests返回的值,我们设置的安全规则主要就是通过这个类设置的,例如下面的代码段
protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().hasRole("USER") .and() .formLogin() .permitAll(); }
通过antMatchers方法,会创建一个AuthorizedUrl,里面的requestMatchers是AntPathRequestMatcher列表,对应的匹配路径是/admin/**,之后调用他的hasRole方法,具体代码在AuthorizedUrl类中,如下
public ExpressionInterceptUrlRegistry hasRole(String role) { return access(ExpressionUrlAuthorizationConfigurer.hasRole(role)); } ... public ExpressionInterceptUrlRegistry access(String attribute) { if (not) { attribute = "!" + attribute; } interceptUrl(requestMatchers, SecurityConfig.createList(attribute)); return ExpressionUrlAuthorizationConfigurer.this.REGISTRY; } ... private void interceptUrl(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) { for (RequestMatcher requestMatcher : requestMatchers) { REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping( requestMatcher, configAttributes)); } }
看到将我们设置好的路径匹配模式和对应的属性追加到了REGISTRY中,通过hasRole方法我们传入的是ADMIN字符串,是如何转换成ConfigAttribute呢,在上面的access方法中,我们看到是调用了SecurityConfig.createList(attribute)来做的
public static List<ConfigAttribute> createList(String... attributeNames) { Assert.notNull(attributeNames, "You must supply an array of attribute names"); List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>( attributeNames.length); for (String attribute : attributeNames) { attributes.add(new SecurityConfig(attribute.trim())); } return attributes; }
就是简单的将我们的字符串包装成ConfigAttribute 的一个具体实现类SecurityConfig。
这样通过
.antMatchers("/admin/**").hasRole("ADMIN")
这样一句配资,我们最终在ExpressionUrlAuthorizationConfigurer的REGISTRY属性中追加了如下一条匹配模式是/admin/**,对应的attributes是包含ADMIN字符串的SecurityConfig。
现在我们再回过头在看下创建SecurityMetadataSource的REGISTRY.createRequestMap方法
final LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> createRequestMap() { if (unmappedMatchers != null) { throw new IllegalStateException( "An incomplete mapping was found for " + unmappedMatchers + ". Try completing it with something like requestUrls().<something>.hasRole('USER')"); } LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>(); for (UrlMapping mapping : getUrlMappings()) { RequestMatcher matcher = mapping.getRequestMatcher(); Collection<ConfigAttribute> configAttrs = mapping.getConfigAttrs(); requestMap.put(matcher, configAttrs); } return requestMap; }
很明显,就是将我们追加到里面的UrlMapping转换成Map返回,最终构造出了一个ExpressionBasedFilterInvocationSecurityMetadataSource返回出去,在这个类的构造函数中,还会做一次转换把配置属性的类型转换成WebExpressionConfigAttribute(在鉴权类中用的Voter类是WebExpressionVoter,对应的属性是WebExpressionConfigAttribute,下面会提到)。
这样SecurityMetadataSource的创建过程就结束了。当一个请求进入FilterSecurityInterceptor中,就利用SecurityMetadataSource中的requestMap对路径进行匹配,找到第一个匹配的配置项后就获取到了对应的ConfigAttribute列表,传入到具体的鉴权类中进行处理。
4. 下面看下AuthenticationManager和AccessDecisionManager如何设置
private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource, AuthenticationManager authenticationManager) throws Exception { FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); securityInterceptor.setSecurityMetadataSource(metadataSource); securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http)); securityInterceptor.setAuthenticationManager(authenticationManager); securityInterceptor.afterPropertiesSet(); return securityInterceptor; }
可以看到authenticationManager直接用的是通过AuthenticationManagerBuilder构建出来后存在Httpsecurity中的对象,AccessDecisionManager是通过getAccessDecisionManager这个方法获取的
private AccessDecisionManager getAccessDecisionManager(H http) { if (accessDecisionManager == null) { accessDecisionManager = createDefaultAccessDecisionManager(http); } return accessDecisionManager; } ... private AccessDecisionManager createDefaultAccessDecisionManager(H http) { AffirmativeBased result = new AffirmativeBased(getDecisionVoters(http)); return postProcess(result); }
在默认情况下,spring 给我们组装了一个AffirmativeBased类,用的Voter类通过getDecisionVoters获取,具体在ExpressionUrlAuthorizationConfigurer类中
@Override @SuppressWarnings("rawtypes") final List<AccessDecisionVoter<? extends Object>> getDecisionVoters(H http) { List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<AccessDecisionVoter<? extends Object>>(); WebExpressionVoter expressionVoter = new WebExpressionVoter(); expressionVoter.setExpressionHandler(getExpressionHandler(http)); decisionVoters.add(expressionVoter); return decisionVoters; }
因为用的是WebExpressionVoter,所以在之前创建SecurityMetadataSource时需要做一次转换。
各种AccessDecisionManager实现类的具体意义我们在讨论鉴权的时候再具体分析。
这样我们的FilterSecurityInterceptor就完全组装好了,并且也作为Filter追加到了servlet中,可以对我们的资源进行保护了。
发表评论
-
spring-security(二十五)鉴权
2018-03-27 11:21 1586前言 本文将详细探讨spring security中的鉴权 ... -
test
2018-03-19 21:20 0什么是服务发现 ... -
spring-security(二十四)CSRF
2018-03-24 09:54 81481.什么是CSRF攻击 下面我们以一个具体的例子来说明这种常见 ... -
spring-security(二十三)Remember-Me认证
2018-03-09 21:06 1327前言: Remember-me认证方式指的是能在不同的会话 ... -
spring-security(二十二)基本认证和摘要认证
2018-03-06 16:58 1787前言: 在web应用中,非常流行以基本认证和摘要认证作为备 ... -
spring-security(二十一)核心Filter-UsernamePasswordAuthenticationFilter
2018-03-04 11:05 1223一、UsernamePasswordAuthenticatio ... -
spring-security(二十)核心Filter-SecurityContextPersistenceFilter
2018-02-28 21:40 1115一、SecurityContextPersistenceFil ... -
spring-security(十九)核心Filter-ExceptionTranslationFilter
2018-02-27 16:31 2041前言: 在spring的安全 ... -
spring-security(二十六)整合CAS 实现SSO
2018-04-05 18:09 12321.cas 认证流程 2.spring security ... -
spring-security(十七)Filter顺序及简介
2018-02-22 18:16 7864前言: spring security在 ... -
spring-security(十六)Filter配置原理
2018-02-21 15:18 2370前言: spring security最常见的应用场景还是 ... -
spring-security(十五) Password编码
2018-02-19 15:15 1215前言: 在实际应用中 ... -
spring-security(十四)UserDetailsService
2018-02-19 11:35 1459前言: 作为spring security的核心类,大多数 ... -
spring-security(十三)核心服务类
2018-02-18 16:46 1399前言: 在之前的篇章中我们已经讲述了spring secu ... -
spring-security(十二)鉴权方式概述
2018-02-18 10:42 2518前言: 本文主要讲述在spring security鉴权的 ... -
spring-security(十一)Web应用认证过程
2018-02-17 17:17 1227前言: 本文将探讨当 ... -
spring-security(十)基本认证过程
2018-02-17 13:55 2086前言: 在spring security中认证具体指的是什 ... -
spring-security(九)-核心组件
2018-02-17 10:46 857前言: 本文主要介绍在spring security中的几 ... -
spring-security(八)java config-sample之cas client
2018-02-16 11:26 2051前言: SSO英文全称Single Sign On,单点登 ... -
spring-security(七)java config-sample之concurrency
2018-02-15 10:51 657前言: 在实际应用中,我们可能会限制一个用户同时登录同一个 ...
相关推荐
基于C51单片机Proteu仿真实例及软件源码+文档说明 之-电子琴.zip
均包含代码,文章,部分项目包含ppt
基于java的智乐健身后台管理系统设计与实现.docx
基于java的鲜花销售管理系统设计与实现.docx
内容概要:本文回顾了近年来关于数字孪生(Digital Twin)的概念和技术的发展历程,并详尽介绍了这种技术在未来车间中的潜在应用场景和需克服的难关。数字孪生是一种用于集成物理和虚拟系统的技术手段,它能够在产品设计、智能生产和预防性维护等多个领域发挥作用。 适合人群:研究人员和工程师们希望更好地理解数字孪生的基本理论与具体应用实践。 使用场景及目标:涵盖了从产品的设计、制造过程到服役阶段故障预测的全过程,并探讨了基于DT的具体实施路径。 其他说明:强调了信息物理系统的交互融合是DT成功部署的基础,而建立高准确度的多维虚拟模型、孪生数据驱动和实现动态实时交互将是推进这一前沿概念向前发展的关键。
管理员能够查看、添加、修改和删除景点分类信息,景点分类管理 用户在系统前台可查看系统信息,包括首页、景点信息、酒店信息以及客房信息等 用户要登录界面可输入用户名、密码,点击登录按钮进行登录系统 项目关键技术 开发工具:IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7+ 后端技术:ssm 前端技术:Vue 关键技术:springboot、SSM、vue、MYSQL、MAVEN 数据库工具:Navicat、SQLyog
关键字:UTM/企业防火墙/NGFW 功能:vpn,sdwan,无线控制器,ldap,双因子认证,nat/透明,终端控制,av防病毒,ips入侵检测,应用控制,web过滤, FortiGate UTM/NGFW产品 ①端口:8口、16口、24口、48口 ②层数:二层(接入层交换机、傻瓜式交换机)、三层(核心交换机、汇聚交换机) ③是否网管 网管: 非网管(傻瓜式交换机,即插即用) WEB网管(S1720GW系列) 全网管(S1720GFR系列,S2700以上的型号都为全网管) ④速率:百兆、千兆、万兆等 1.带机量(支持用户数) 2.端口数 3.吞吐量,并发连接数 4.功能 功能差异须知 NG-xxxx产品特有功能 TG-xxxx&NG-xxxx共有功能 TG-xxxx产品特有功能 FW:网络接入、安全防护、高可用性、身份认证、系统服务、系统管理 ●应用层DDOS攻击防护 负载均衡:多链路负载均衡与备份、多链路智能选路技术、多算法的服务器负载均衡 ●异常行为分析:内置统计只能算法,智能学习
简化设计,轻松管理 一键设计:快速创建和管理SQLite3数据库,简化数据库设计流程。 高效查询:强大的查询功能,帮助您轻松处理复杂的SQL语句。 功能全面,灵活便捷 可视化界面:直观的图形界面,让您无需编写繁琐的SQL代码,即可完成数据库设计。 数据同步:支持实时数据同步,确保您的数据库始终保持最新状态。 高度兼容,广泛适用 跨平台支持:适用于Windows、Mac和Linux等多种操作系统,满足不同开发环境的需求。 多语言集成:与C、C++等主流编程语言无缝对接,提高开发效率。 安全可靠,稳定运行 数据备份:内置数据备份与恢复功能,保障数据安全。 性能优化:优化数据库结构,提升查询速度和存储效率。
小程序-滴滴作业.zip 小程序-滴滴作业.zip 小程序-滴滴作业.zip
地线贴标_复制.ezd
Chrome主题-开阔绿地草地主题
基于java校园兼职平台设计与实现.docx
基于java的旅游管理系统设计与实现.docx
基于java的技术大健康综合咨询问诊平台的设计与实现.docx
均包含代码,文章,部分项目包含ppt
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
基于java的共享客栈管理系统设计与实现.docx
基于java的车库智能管理平台设计与实现.docx
基于java的学生宿舍管理设计与实现.docx
【C++】项目设计资源 【C++】新手入门教程 包含例子和相关说明