Arch - 架构安全性_验证(Verification)
https://i-blog.csdnimg.cn/direct/122f628bd8654641896ff1e34037a513.png#pic_centerOverView
即使只限定在“软件架构设计”这个语境下,体系安全仍旧是一个很大的话题。
接下来我们将对体系安全架构的各个方面进行具体分析,包罗认证、授权、凭证、保密、传输安全和验证,结合案例实践,展示怎样应用这些安全原则和技术,讨论具体解决方案和行业标准 ,并提供与业界标准相同等的解决方案。
计划:
[*] 认证(Authentication):
[*]介绍认证的基本概念及其在软件架构中的作用。
[*]讨论常见的认证方法(如用户名/暗码、双因素认证、生物识别)及其实现方式。
[*]探讨行业标准和最佳实践(如 OAuth、OpenID Connect)。
[*] 授权(Authorization):
[*]定义授权的概念及其紧张性。
[*]解说不同的授权模型(如基于角色的访问控制RBAC、基于属性的访问控制ABAC)。
[*]介绍如安在架构中实现这些模型以及怎样处置处罚权限管理。
[*] 凭证(Credential):
[*]分析凭证的作用及其管理方式。
[*]讨论怎样确保证书和凭证的真实性、完备性和不可抵赖性。
[*]介绍现有的凭证管理方案和技术(如 PKI、公钥底子办法)。
[*] 保密(Confidentiality):
[*]解释数据保密的基本概念及其在体系中的应用。
[*]讨论数据加密的技术和计谋(如对称加密、非对称加密)。
[*]介绍怎样确保保密性,包罗数据存储和处置处罚中的加密措施。
[*] 传输(Transport Security):
[*]定义传输安全及其对体系安全的影响。
[*]解说怎样实现传输层安全(如 TLS/SSL)的具体方法。
[*]讨论怎样掩护网络通讯免受中间人攻击和数据篡改。
[*] 验证(Verification):
[*]介绍数据验证的必要性及其对体系稳定性的影响。
[*]讨论常见的验证技术(如输入验证、数据完备性检查)。
[*]解说如安在体系中实现数据验证机制以保证数据同等性和正确性。
导图
https://i-blog.csdnimg.cn/direct/e3075c2127bb4fc2b3eb856a0a4f54e5.jpeg
专家:软件开发 > 数据验证专家
要求:对数据验证的全面分析,包罗最佳实践、常见问题息争决方案,重点讨论 Java 中的 Bean Validation
计划:
[*]弁言:数据验证的紧张性
[*]数据验证的基本概念
[*]数据验证的层次
[*]前端验证
[*]后端验证
[*]数据验证的标准做法
[*]Java Bean Validation
[*]自定义校验注解
[*]校验结果的处置处罚
[*]性能思量与副作用
[*]总结与未来展望
1. 弁言:数据验证的紧张性概述
数据验证不仅是确保用户输入正确性的本事,也是维护体系稳定性、数据同等性和安全性的紧张措施。
2. 数据验证的基本概念
数据验证是指在数据被处置处罚或存储之前,对其进行检查以确保数据符合预定义的规则。验证可以包罗:
[*]格式验证:确保数据符合预期的格式(如邮箱、电话号码)。
[*]业务规则验证:确保数据符合特定的业务逻辑(如用户唯一性)。
3. 数据验证的层次
前端验证
前端验证通常通过JavaScript进行,可以大概提供即时反馈,减少无效哀求。这种验证可以捕捉一些基本错误,但并不足以替代后端验证。
后端验证
后端验证是确保数据在被处置处罚进步行全面检查的关键。它可以防止不合法的数据通过API提交到服务器,并对业务逻辑进行严格控制。
4. 数据验证的标准做法
在Java中,接纳Java Bean Validation(JSR 380)是进行数据验证的标准方法。该规范支持一系列内置的校验注解,如@NotNull、@Email、@Size等。
[*]注解驱动:通过在Bean类的属性上使用注解定义校验规则。
[*]统一管理:所有校验逻辑集中于Bean中,便于管理和维护。
5. 自定义校验注解
当内置注解无法满意业务需求时,可以自定义校验注解。比方,在用户注册中,需要确保用户名的唯一性。
与业务相关的校验往往才是最复杂的校验,将简朴的校验交给 Bean Validation,而把复杂的校验留给自己,这简直是买椟还珠故事的程序员版本。其实以 Bean Validation 的标准方式来做业务校验是非常优雅的
/**
* 创建新的用户
*/
@POST
public Response createUser(@Valid @UniqueAccount Account user) {
return CommonResponse.op(() -> service.createAccount(user));
}
/**
* 更新用户信息
*/
@PUT
@CacheEvict(key = "#user.username")
public Response updateUser(@Valid @AuthenticatedAccount @NotConflictAccount Account user) {
return CommonResponse.op(() -> service.updateAccount(user));
}
注意其中的三个自定义校验注解,它们的寄义分别是:
[*]@UniqueAccount:传入的用户对象必须是唯一的,不与数据库中任何已有用户的名称、手机、邮箱产生重复。
[*]@AuthenticatedAccount:传入的用户对象必须与当前登录的用户同等。
[*]@NotConflictAccount:传入的用户对象中的信息与其他用户是无冲突的,譬如将一个注册用户的邮箱,修改成与另外一个已存在的注册用户同等的值,这便是冲突。
这里的需求很容易明白,注册新用户时,应约束不与任何已有用户的关键信息重复;而修改自己的信息时,只能与自己的信息重复,而且只能修改当前登录用户的信息。这些约束规则不仅仅为这两个方法服务,它们可能会在用户资源中的其他入口被使用到,乃至在其他分层的代码中被使用到,在 Bean 上做校验就能一揽子地覆盖上述这些使用场景。下
下面代码是这三个自定义注解对应校验器的实现类
public static class AuthenticatedAccountValidator extends AccountValidation<AuthenticatedAccount> {
public void initialize(AuthenticatedAccount constraintAnnotation) {
predicate = c -> {
AuthenticAccount loginUser = (AuthenticAccount) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return c.getId().equals(loginUser.getId());
};
}
}
public static class UniqueAccountValidator extends AccountValidation<UniqueAccount> {
public void initialize(UniqueAccount constraintAnnotation) {
predicate = c -> !repository.existsByUsernameOrEmailOrTelephone(c.getUsername(), c.getEmail(), c.getTelephone());
}
}
public static class NotConflictAccountValidator extends AccountValidation<NotConflictAccount> {
public void initialize(NotConflictAccount constraintAnnotation) {
predicate = c -> {
Collection<Account> collection = repository.findByUsernameOrEmailOrTelephone(c.getUsername(), c.getEmail(), c.getTelephone());
// 将用户名、邮件、电话改成与现有完全不重复的,或者只与自己重复的,就不算冲突
return collection.isEmpty() || (collection.size() == 1 && collection.iterator().next().getId().equals(c.getId()));
};
}
}
这样业务校验便和业务逻辑就完全分离开来,在需要校验时用@Valid注解自动触发,或者通过代码手动触发执行,可根据你们项目的要求,将这些注解应用于控制器、服务层、持久层等任何层次的代码之中。此外,校验结果不满意时的提示信息,也便于统一处置处罚,如提供默认值、提供国际化支持 、提供统一的客户端返回格式(创建一个用于ConstraintViolationException的异常处置处罚器来实现.
对于 Bean 与 Bean 校验器,笔者另外有两条编码发起。第一条是对校验项预置好默认的提示信息,这样当校验不通过时用户能获得明确的修正提示,以下是代码示例:
/**
* 表示一个用户的信息是无冲突的
*
* “无冲突”是指该用户的敏感信息与其他用户不重合,譬如将一个注册用户的邮箱,修改成与另外一个已存在的注册用户一致的值,这便是冲突
**/
@Documented
@Retention(RUNTIME)
@Target({FIELD, METHOD, PARAMETER, TYPE})
@Constraint(validatedBy = AccountValidation.NotConflictAccountValidator.class)
public @interface NotConflictAccount {
String message() default "用户名称、邮箱、手机号码与现存用户产生重复";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
另外一条发起是将不带业务寄义的格式校验注解放到 Bean 的类定义之上,将带业务逻辑的校验放到 Bean 的类定义的外面。这两者的区别是放在类定义中的注解可以大概自动运行,而放到类外面则需要像前面代码那样,明确标出注解时才会运行。譬如用户账号实体中的部门代码为:
public class Account extends BaseEntity {
@NotEmpty(message = "用户不允许为空")
private String username;
@NotEmpty(message = "用户姓名不允许为空")
private String name;
private String avatar;
@Pattern(regexp = "1\\d{10}", message = "手机号格式不正确")
private String telephone;
@Email(message = "邮箱格式不正确")
private String email;
}
这些校验注解都直接放在类定义中,每次执行校验的时候它们都会被运行。由于 Bean Validation 是 Java 的标准规范,它执行的频率可能比编写代码的程序所预想的要更高,譬如使用 Hibernate 来做持久化时,便会自动执行 Data Object 上的校验注解。对于那些不带业务寄义的注解,运行是不需要其他外部资源到场的,不会调用远程服务、访问数据库,这种校验重复执行并没有什么成本。
但带业务逻辑的校验,通常就需要外部资源到场执行,这不仅仅是多消耗一点时间和运算资源的问题,由于很难保证依赖的每个服务都是幂等的,重复执行校验很可能会带来额外的副作用。因此应该放到外面让使用者自行判定是否要触发。
另有一些“需要触发一部门校验”的非典型情况,譬如“新增”利用 A 需要执行全部校验规则,“修改”利用 B 中希望不校验某个字段,“删除”利用 C 中希望改变某一条校验规则,这时候要就要启用分组校验来处置处罚,设计一套“新增”、“修改”、“删除”这样的标识类,置入到校验注解的groups参数中去实现
6. 校验结果的处置处罚
有用的校验结果处置处罚是提升用户体验的关键。当校验失败时,体系应返回清楚的错误信息,引导用户进行修正。使用统一的异常处置处罚机制可以实现这一点。
@ControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleValidationException(ConstraintViolationException ex) {
// 返回错误信息
}
}
7. 性能思量与副作用
在进行业务校验时,应注意校验的幂等性和性能。假如校验涉及到数据库查询,重复执行可能会引发不必要的性能开销或副作用。发起将格式验证放在Bean定义中,而将业务逻辑验证移至外部,以避免不必要的重复。
8. 小结
数据验证是软件开发中的一项基本而紧张的任务。通过公道使用Java Bean Validation,结合自定义注解和统一处置处罚机制,可以大概有用提高体系的稳定性与数据质量。
https://i-blog.csdnimg.cn/direct/34a0f05c73fa431287cef8137e7d7ba4.jpeg#pic_center
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]