新版Spring Security6.2架构 (三) - Authorization

news2024/7/6 9:42:31

前言

书接上文,在经过了authentication后就是authorization了,本文还是对官网文档authorization的一个架构翻译和个人理解,后续的博客在写具体使用例子,从数据中认证,融合authentication和authorization的概念。

Authorization 架构

Authorization就是在确定用户进行身份验证的方式后,还需要配置应用进程的授权规则。

Spring Security 中之所以这么受到那么多人信任和欢迎,高级授权功能是其原因之一。无论您选择如何进行身份验证(无论是使用 Spring Security 提供的机制和提供进程,还是与容器或其他非 Spring Security 身份验证机构集成),都可以在应用进程中以一致且简单的方式使用授权服务。 

应考虑把授权规则附加在请求 URIs路径和方法上。下面还有大量关于Spring Security授权如何工作的细节,以及在创建了基本模型后,如何对其进行微调。

Authorization 架构

Authorities

Authentication讨论的是所有Authentication的实现,以及如何存储 GrantedAuthority 对象的列表。这些代表已授予委托人的权限。GrantedAuthority 对象由 AuthenticationManager 插入到 Authentication 对象中,在后续中由 AccessDecisionManager 实例读取来实现授权决策。
GrantedAuthority接口只有一个方法

String getAuthority();

AuthorizationManager 实例使用此方法来获取 GrantedAuthority 准确的字符串表示形式。通过以字符串形式返回表示形式,大多数 AuthorizationManager 实现可以轻松“读取”GrantedAuthority。如果 GrantedAuthority 无法准确表示为字符串,则 GrantedAuthority 被视为“复杂”,并且 getAuthority() 必须返回 null。

GrantedAuthority复杂的实现在于存储适用于不同客户帐号的操作和权限阈值列表。将这个复杂的 GrantedAuthority 表示为字符串将非常困难。因此,getAuthority() 方法应返回 null。这向任何 AuthorizationManager 表明它需要支持特定的 GrantedAuthority 实现才能理解其内容。

Spring Security 包含一种具体的 GrantedAuthority 实现:SimpleGrantedAuthority。此实现允许将任何用户指定的字符串转换为 GrantedAuthority。安全架构中包含的所有 AuthenticationProvider 实例都使用 SimpleGrantedAuthority 来填充 Authentication 对象。

默认情况下,基于角色的授权规则包含 ROLE_ 作为前缀。这意味着,如果有一个授权规则要求安全上下文具有“USER”角色,Spring Security 将默认查找返回“ROLE_USER”的 GrantedAuthority#getAuthority。

您可以使用 GrantedAuthorityDefaults 对此进行自定义。 GrantedAuthorityDefaults 的存在是为了允许自定义用于基于角色的授权规则的前缀。

您可以通过公开 GrantedAuthorityDefaults bean 将授权规则配置为使用不同的前缀,如下所示:

@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {
	return new GrantedAuthorityDefaults("MYPREFIX_");
}

这边官网还有个提示:

可以使用静态方法公开 GrantedAuthorityDefaults,以确保 Spring 在初始化 Spring Security 的方法安全性@Configuration类之前发布它

Invocation Handling

Spring Security 提供了拦截器来控制对安全对象(例如方法调用或 Web 请求)的访问。调用前决定是否允许调用继续由 AuthorizationManager 实例做出。此外,调用后是否可返回给定值的决策由 AuthorizationManager 实例做出。

The AuthorizationManager

AuthorizationManager 取代了 AccessDecisionManager 和 AccessDecisionVoter。 

使用自定义 AccessDecisionManager 或 AccessDecisionVoter 的应用程序建议更改为使用 AuthorizationManager。AuthorizationManager 接口包含两种方法:

AuthorizationManager 是通过 Spring Security 基于请求、基于方法和基于消息的授权组件来调用,并负责做出最终的访问控制决策。AuthorizationManager 接口包含两种方法:

AuthorizationDecision check(Supplier<Authentication> authentication, Object secureObject);

default AuthorizationDecision verify(Supplier<Authentication> authentication, Object secureObject)
        throws AccessDeniedException {
    // ...
}

AuthorizationManager 的检查方法将传递它需要的所有相关信息,以便做出授权决策。具体而言,传递安全对象可以检查实际安全对象调用中包含的那些参数。例如,假设安全对象是 MethodInvocation。很容易在 MethodInvocation 中查询任何 Customer 参数,然后在 AuthorizationManager 中实现某种安全逻辑,以确保允许主体对该客户进行操作。如果授予访问权限,则实现应返回正 AuthorizationDecision,如果访问被拒绝,则返回负 AuthorizationDecision,在弃权时返回空 AuthorizationDecision。

verify 调用检查,随后在负 AuthorizationDecision 的情况下引发 AccessDeniedException。

基于委托的 AuthorizationManager 实现

虽然用户可以实现自己的 AuthorizationManager 来控制授权的所有方面,但 Spring Security 附带了一个委托 AuthorizationManager,它可以与各个 AuthorizationManager 协作。

RequestMatcherDelegatingAuthorizationManager 会将请求与最合适的委托AuthorizationManager 进行匹配。为了方法安全性,可以使用 AuthorizationManagerBeforeMethodInterceptor 和 AuthorizationManagerAfterMethodInterceptor。

Authorization Manager Implementations阐释它的相关类。

使用此方法,可以在授权决策上轮询 AuthorizationManager 实现一系列组合。

AuthorityAuthorizationManager

Spring Security 提供的最常见的 AuthorizationManager 是 AuthorityAuthorizationManager。它配置了一组给定的权限,以在当前Authentication身份验证上查找。如果 Authentication 包含任何已配置的authorities,它将返回正 AuthorizationDecision。否则,它将返回负的 AuthorizationDecision。

AuthenticatedAuthorizationManager

另一个管理器是 AuthenticatedAuthorizationManager。它可用于区分匿名用户、完全身份验证用户和“记住我”身份验证的用户。许多站点允许在“记住我”身份验证下进行某些有限的访问,但要求用户通过登录来确认其身份才能获得完全访问权限。

AuthorizationManagers

AuthenticationManagers 中还有有用的静态工厂,用于将单个 AuthenticationManager 组合成更复杂的表达式。

Custom Authorization Managers

显然,您还可以实现自定义 AuthorizationManager,并且可以将所需的任何访问控制逻辑放入其中。它可能特定于您的应用程序(与业务逻辑相关),也可能实现某些安全管理逻辑。例如,您可以创建一个可以查询 Open Policy Agent 或您自己的授权数据库的实现。

小提示:您可以在 Spring 网站上找到一篇博客文章,其中介绍了如何使用旧AccessDecisionVoter 实时拒绝帐户已被暂停的用户的访问。可以通过改为实现 AuthorizationManager 来实现相同的结果。

AccessDecisionManager 和 AccessDecisionVoters 调整

在 AuthorizationManager 之前,Spring Security 发布了 AccessDecisionManager 和 AccessDecisionVoter。

在某些情况下,例如迁移较旧的应用程序,可能需要引入调用 AccessDecisionManager 或 AccessDecisionVoter 的 AuthorizationManager。

要调用现有的 AccessDecisionManager, 可以如下:

@Component
public class AccessDecisionManagerAuthorizationManagerAdapter implements AuthorizationManager {
    private final AccessDecisionManager accessDecisionManager;
    private final SecurityMetadataSource securityMetadataSource;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
        try {
            Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
            this.accessDecisionManager.decide(authentication.get(), object, attributes);
            return new AuthorizationDecision(true);
        } catch (AccessDeniedException ex) {
            return new AuthorizationDecision(false);
        }
    }

    @Override
    public void verify(Supplier<Authentication> authentication, Object object) {
        Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
        this.accessDecisionManager.decide(authentication.get(), object, attributes);
    }
}

然后将其连接到您的 SecurityFilterChain。

或者,若要仅调用 AccessDecisionVoter,可以执行以下操作:

@Component
public class AccessDecisionVoterAuthorizationManagerAdapter implements AuthorizationManager {
    private final AccessDecisionVoter accessDecisionVoter;
    private final SecurityMetadataSource securityMetadataSource;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
        Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
        int decision = this.accessDecisionVoter.vote(authentication.get(), object, attributes);
        switch (decision) {
        case ACCESS_GRANTED:
            return new AuthorizationDecision(true);
        case ACCESS_DENIED:
            return new AuthorizationDecision(false);
        }
        return null;
    }
}

然后将其连接到您的安全过滤链中。

角色层次-Hierarchical Roles

应用程序的通常需求,一个特定角色应自动“包含”其他角色。例如,在具有“管理员”和“用户”角色概念的应用程序中,您可能希望管理员能够执行普通用户所能做的所有事情。为此,您可以确保所有管理员用户也被分配了“用户”角色。或者,您可以修改每个访问约束,要求“用户”角色也包括“管理员”角色。如果您的应用程序中有很多不同的角色,这可能会变得非常复杂。

使用角色层次结构可以配置哪些角色(或权限)应包括其他角色。Spring Security 的 RoleVoter 的扩展版本 RoleHierarchyVoter 配置了 RoleHierarchy,它从中获取分配给用户的所有“可访问权限”。典型配置可能如下所示:

@Bean
static RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
    hierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF\n" +
            "ROLE_STAFF > ROLE_USER\n" +
            "ROLE_USER > ROLE_GUEST");
    return hierarchy;
}

// and, if using method security also add
@Bean
static MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {
	DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
	expressionHandler.setRoleHierarchy(roleHierarchy);
	return expressionHandler;
}

温馨提示:RoleHierarchy Bean 配置尚未移植到 @EnableMethodSecurity。因此,此示例使用的是 AccessDecisionVoter。如果需要 RoleHierarchy 支持方法安全性,请继续使用 @EnableGlobalMethodSecurity,直到 github.com/spring-projects/spring-security/issues/12783 完成。

在这里,我们在层次结构ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST中有四个角色。使用 ROLE_ADMIN 进行身份验证的用户在针对适用于调用上述 RoleHierarchyVoter 的 AuthorizationManager 评估安全约束时,其行为将被视为具有所有四个角色。>符号可以被认为是“包括”的意思。

角色层次结构提供了一种方便的方法,可以简化应用程序的访问控制配置数据和/或减少需要分配给用户的权限数量。对于更复杂的要求,您可能希望在应用程序所需的特定访问权限和分配给用户的角色之间定义逻辑映射,以便在加载用户信息时在两者之间进行转换。

旧版授权组件

Spring Security 包含一些遗留组件。由于它们尚未删除,因此出于历史目的包含文档。他们推荐的替代品如上所述。

The AccessDecisionManager

AccessDecisionManager 由 AbstractSecurityInterceptor 调用,负责做出最终的访问控制决策。AccessDecisionManager 接口包含三种方法:

void decide(Authentication authentication, Object secureObject,
	Collection<ConfigAttribute> attrs) throws AccessDeniedException;

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

AccessDecisionManager 的 decide 方法传递了做出授权决策所需的所有相关信息。具体而言,传递安全对象可以检查实际安全对象调用中包含的那些参数。例如,假设安全对象是 MethodInvocation。您可以在 MethodInvocation 中查询任何 Customer 参数,然后在 AccessDecisionManager 中实现某种安全逻辑,以确保允许主体对该客户进行操作。如果访问被拒绝,则实现应引发 AccessDeniedException。

supports(ConfigAttribute) 方法由 AbstractSecurityInterceptor 在启动时调用,以确定 AccessDecisionManager 是否可以处理传递的 ConfigAttribute。supports(Class) 方法由安全侦听器实现调用,以确保配置的 AccessDecisionManager 支持安全侦听器提供的安全对象类型。

基于投票的 AccessDecisionManager 实现

虽然用户可以实现自己的 AccessDecisionManager 来控制授权的所有方面,但 Spring Security 包含多个基于投票的 AccessDecisionManager 实现。投票决策管理器描述了相关类。

下图显示了 AccessDecisionManager 接口:

通过使用此方法,将针对授权决策轮询一系列 AccessDecisionVoter 实现。然后,AccessDecisionManager 根据其对投票的评估决定是否引发 AccessDeniedException。

AccessDecisionVoter 接口有三种方法:

int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

具体实现返回一个 int,可能的值反映在名为 ACCESS_ABSTAIN、ACCESS_DENIED 和 ACCESS_GRANTED 的 AccessDecisionVoter 静态字段中。如果投票实现对授权决策没有反对,则返回 ACCESS_ABSTAIN。如果它确实有反对意见,它必须返回ACCESS_DENIED或ACCESS_GRANTED。

Spring Security 提供了三个具体的 AccessDecisionManager 实现来统计投票。ConsensusBased 实现根据非弃权票的共识授予或拒绝访问。提供属性以控制在票数相等或所有票数均弃权的情况下的行为。如果收到一个或多个ACCESS_GRANTED投票,则 AffirmativeBased 实现将授予访问权限(换句话说,如果至少有一个授予投票,则将忽略拒绝投票)。与 ConsensusBased 实现一样,如果所有投票者都弃权,则有一个参数来控制行为。UnanimousBased 提供程序期望获得一致的 ACCESS_GRANTED 票才能授予访问权限,而忽略了弃权票。如果有任何ACCESS_DENIED投票,它将拒绝访问。与其他实现一样,有一个参数用于控制所有投票者弃权时的行为。

您可以实现一个自定义 AccessDecisionManager,它以不同的方式计算投票。例如,来自特定 AccessDecisionVoter 的投票可能会获得额外的权重,而来自特定投票者的拒绝投票可能会产生否决权效应。

投票角色RoleVoter

Spring Security 提供的最常用的 AccessDecisionVoter 是 RoleVoter,它将配置属性视为角色名称,并在用户被分配了该角色时投票授予访问权限。

如果任何 ConfigAttribute 以 ROLE_ 前缀开头,它将投票。如果存在一个 GrantedAuthority,它返回的 String 表示形式(来自 getAuthority() 方法)与一个或多个以 ROLE_ 前缀开头的 ConfigAttributes 完全相等,则它会投票授予访问权限。如果任何以 ROLE_ 开头的 ConfigAttribute 没有完全匹配,则 RoleVoter 将投票拒绝访问。如果没有 ConfigAttribute 以 ROLE_ 开头,则投票者弃权。

AuthenticatedVoter

我们隐式看到的另一个投票者是 AuthenticatedVoter,它可用于区分匿名、完全身份验证和记住我身份验证的用户。许多站点允许在“记住我”身份验证下进行某些有限的访问,但要求用户通过登录来确认其身份才能获得完全访问权限。

当我们使用 IS_AUTHENTICATED_ANONYMOUSLY 属性授予匿名访问权限时,此属性正在由 AuthenticatedVoter 处理。有关详细信息,请参阅 AuthenticatedVoter。

自定义投票器Custom Voters

您还可以实现自定义 AccessDecisionVoter,并在其中放置所需的任何访问控制逻辑。它可能特定于您的应用程序(与业务逻辑相关),也可能实现某些安全管理逻辑。例如,在 Spring 网站上,您可以找到一篇博客文章,该文章介绍了如何使用投票者实时拒绝帐户已被暂停的用户的访问。

与 Spring Security 的许多其他部分一样,AfterInvocationManager 有一个具体的实现,即 AfterInvocationProviderManager,它轮询 AfterInvocationProviders 列表。允许每个 AfterInvocationProvider 修改返回对象或引发 AccessDeniedException。事实上,多个提供程序可以修改对象,因为前一个提供程序的结果将传递给列表中的下一个提供程序。

请注意,如果您使用的是 AfterInvocationManager,您仍然需要允许 MethodSecurityInterceptor 的 AccessDecisionManager 允许操作的配置属性。如果您使用的是典型的 Spring Security 包含的 AccessDecisionManager 实现,则没有为特定的安全方法调用定义配置属性将导致每个 AccessDecisionVoter 弃权。反过来,如果 AccessDecisionManager 属性“allowIfAllAbstainDecisions”为 false,则将引发 AccessDeniedException。您可以通过以下任一方式避免此潜在问题:(i) 将“allowIfAllAbstainDecisions”设置为 true(尽管通常不建议这样做)或 (ii) 仅确保 AccessDecisionVoter 将投票授予访问权限的至少一个配置属性。后一种(推荐)方法通常通过ROLE_USER或ROLE_AUTHENTICATED配置属性来实现。

参考文献:

《Spring bott官网》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1302450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

堆的相关时间复杂度计算(C语言)

目录 前言 建堆的时间复杂度 向上调整建堆的时间复杂度 向下调整建堆的时间复杂度 维护堆的时间复杂度 top K问题的时间复杂度 前言 在前面的三篇文章中我们成功的实现了堆排序的升降序以及基于堆的top K问题&#xff0c;现在我们来解决它们的时间复杂度问题 建堆的时间…

【精选】 VulnHub (超详细解题过程)

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

前后端请求之nginx配置

问题&#xff1a; 前端发送的请求&#xff0c;是如何请求到后端服务器的&#xff1f; 如&#xff0c;前端请求地址&#xff1a;http://loclhost/api/employee/login&#xff1a; 后端相应请求地址&#xff1a;http://loclhost:8080/admin/employee/login 回答&#xff1a; …

Firmware Analysis Plus (Fap)固件模拟安装教程(最新)

最近在搞IoT的研究&#xff0c;但是难在设备比较难弄&#xff0c;只有固件&#xff0c;而没有设备&#xff0c;买吧&#xff0c;又太费钱&#xff0c;不划算。好在有很多项目可以在模拟环境中运行固件。但是几乎没有一个平台能够模拟所有硬件设备。IoT产品的架构也不尽相同。 …

Idea spring项目中 resource图标错误解决方案

1.resources错误显示示例 2.resources正确显示示例 3.解决方案 第一步&#xff1a; 第二步&#xff1a; 点击完成即可。

Zidebactam sodium salt β-内酰胺酶抑制剂 1706777-46-9科研

Zidebactam sodium salt β-内酰胺酶抑制剂 1706777-46-9 &#xff08;源自星戈瑞&#xff09; ATH686 FLT3 抑制剂 853299-52-2 Pelitrexol 抑制剂 446022-33-9 TBT1 转运蛋白抑制剂 52535-76-9 HFY-4A HDAC 抑制剂 2094810-82-7 SDR-04 BET 抑制剂 879593-54-1 Phthala…

Java项目-瑞吉外卖Day3

填充公共字段&#xff1a; 目的&#xff1a;由于某些属性&#xff0c;例如createdTime这些需要填充的字段会在多个地方出现&#xff0c;所以考虑使用公共字段自动填充的办法减少重复代码。 在对应属性上加入TableField注解。通过fill字段表明策略&#xff0c;是插入/更新的时候…

国内大厂机器人赛道产品

大疆 大疆无人机自然不必说&#xff0c;除此之外大疆搞机甲大师&#xff0c;教育机器人。 字节 当前字节在机器人领域只是初步探索阶段&#xff0c;目前尚未发布相关产品&#xff08;截止至23.12&#xff09;。 管理层想法&#xff1a; 跟已有业务做结合&#xff0c;服务好…

机器学习之全面了解回归学习器

我们将和大家一起探讨机器学习与数据科学的主题。 本文主要讨论大家针对回归学习器提出的问题。我将概要介绍&#xff0c;然后探讨以下五个问题&#xff1a; 1. 能否将回归学习器用于时序数据&#xff1f; 2. 该如何缩短训练时间&#xff1f; 3. 该如何解释不同模型的结果和…

Swift “黑魔法”之动态获取类实例隐藏属性的值

概览 在 Swift 代码的调试中,我们时常惊叹调试器的无所不能:对于大部分“黑盒”类实例的内容,调试器也都能探查的一清二楚。 想要自己在运行时也能轻松找到 Thread 实例“私有”属性的值吗(比如 seqNum)? 在本篇博文中您将学到如下内容: 概览1. 借我,借我,一双慧眼吧…

重磅!2023中国高校计算机大赛-人工智能创意赛结果出炉

目录 中国计算机大赛-人工智能创意赛现场C4-AI大赛颁奖及留影800个AI应用&#xff1f;这届大学生真能“搞事情”AI原生时代&#xff0c;百度要再培养500万大模型人才 中国计算机大赛-人工智能创意赛现场 12月8日&#xff0c;杭州&#xff0c;一位“白发老人”突然摔倒在地&…

UIUC北大最新工作Radarize:室内环境大规模雷达SLAM

0. 笔者个人体会 相对视觉和LiDAR SLAM来说,基于Radar的SLAM较为小众。但视觉SLAM对光照和低纹理区域敏感,在室内使用还有隐私问题。LIDAR SLAM在长走廊、雾烟尘等退化环境效果不好。所以在一些专用领域,Radar SLAM还是有不可替代的价值。 今天笔者将为大家分享伊利诺伊大学…

Web网站服务(二)

1、客户机地址限制。 Require all granted&#xff1a;表示允许所有主机访问。 Require all denied&#xff1a;表示拒绝所有主机访问。 Require local&#xff1a;表示仅允许本地主机访问。 Require [not] host <主机名或域名列表>&#xff1a;表示允许或拒绝指定主机或…

RabbitMQ反序列化未经授权的类异常解决方案

配置好生产者消费者后&#xff0c;消费者项目启动后出现如下异常&#xff1a; Caused by: java.lang.SecurityException: Attempt to deserialize unauthorized 这是反序列化未经授权的类&#xff0c;解决办法是设置信任所有消息发起者&#xff0c;可以将环境变量&#xff1a; …

day40-43-Vue2.js-路由VueRouter-Vuex状态管理-Axios异步

今日内容 零、 复习昨日 一、Vue简介 1.1 简介 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式的js框架&#xff0c;发布于 2014 年 2 月。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#x…

Windows Terminal的半透明效果

打开Windows Terminal的半透明效果 最终实现效果&#xff1a; 系统&#xff1a;win11 23H2 步骤&#xff1a; 1.winx打开终端 2.右键打开设置 3.打开外观->亚克力材料开启 4.默认值->外观->透明度&#xff0c;按喜好选择即可

018 OpenCV 人脸检测

目录 一、环境 二、分类器原理 2.1、概述 2.2、工作原理 三、人脸检测代码 一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、分类器原理 CascadeClassifier是OpenCV&#xff08;开源计算机视觉库&#xff09;中的一个强大的类…

【论文解读】Accelerating motion estimation by genetic algorithm approach in x265

时间&#xff1a;2018 级别&#xff1a;SCI 机构&#xff1a;College of Engineering Pune 摘要&#xff1a; 在过去 20 年&#xff0c;在视频编码和压缩领域&#xff0c;研究人员提出了几种减少运动估计的计算量和时间的技术&#xff0c;本文提出了一种基于遗传算法初始种群确…

一篇文章带你全面了解Web UI自动化测试之元素定位

前言 目前&#xff0c;在自动化测试的实际应用中&#xff0c;接口自动化测试被广泛使用&#xff0c;但UI自动化测试也并不会被替代。让我们看看二者的对比&#xff1a; 接口自动化测试是跳过前端界面直接对服务端的测试&#xff0c;执行效率和覆盖率更高&#xff0c;维护成本…