Arch - 架构安全性_验证(Verification)

news2024/9/29 9:27:23

文章目录

  • OverView
  • 导图
  • 1. 引言:数据验证的重要性概述
  • 2. 数据验证的基本概念
  • 3. 数据验证的层次
    • 前端验证
    • 后端验证
  • 4. 数据验证的标准做法
  • 5. 自定义校验注解
  • 6. 校验结果的处理
  • 7. 性能考虑与副作用
  • 8. 小结

在这里插入图片描述

OverView

即使只限定在“软件架构设计”这个语境下,系统安全仍然是一个很大的话题。

接下来我们将对系统安全架构的各个方面进行详细分析,包括认证、授权、凭证、保密、传输安全和验证,结合案例实践,展示如何应用这些安全原则和技术,讨论具体解决方案和行业标准 ,并提供与业界标准相一致的解决方案。

计划:

  1. 认证(Authentication)

    • 介绍认证的基本概念及其在软件架构中的作用。
    • 讨论常见的认证方法(如用户名/密码、双因素认证、生物识别)及其实现方式。
    • 探讨行业标准和最佳实践(如 OAuth、OpenID Connect)。
  2. 授权(Authorization)

    • 定义授权的概念及其重要性。
    • 讲解不同的授权模型(如基于角色的访问控制RBAC、基于属性的访问控制ABAC)。
    • 介绍如何在架构中实现这些模型以及如何处理权限管理。
  3. 凭证(Credential)

    • 阐明凭证的作用及其管理方式。
    • 讨论如何确保证书和凭证的真实性、完整性和不可抵赖性。
    • 介绍现有的凭证管理方案和技术(如 PKI、公钥基础设施)。
  4. 保密(Confidentiality)

    • 解释数据保密的基本概念及其在系统中的应用。
    • 讨论数据加密的技术和策略(如对称加密、非对称加密)。
    • 介绍如何确保保密性,包括数据存储和处理中的加密措施。
  5. 传输(Transport Security)

    • 定义传输安全及其对系统安全的影响。
    • 讲解如何实现传输层安全(如 TLS/SSL)的具体方法。
    • 讨论如何保护网络通信免受中间人攻击和数据篡改。
  6. 验证(Verification)

    • 介绍数据验证的必要性及其对系统稳定性的影响。
    • 讨论常见的验证技术(如输入验证、数据完整性检查)。
    • 讲解如何在系统中实现数据验证机制以保证数据一致性和正确性。

导图

在这里插入图片描述


专家:软件开发 > 数据验证专家
要求:对数据验证的全面分析,包括最佳实践、常见问题和解决方案,重点讨论 Java 中的 Bean Validation

计划:

  1. 引言:数据验证的重要性
  2. 数据验证的基本概念
  3. 数据验证的层次
    • 前端验证
    • 后端验证
  4. 数据验证的标准做法
    • Java Bean Validation
  5. 自定义校验注解
  6. 校验结果的处理
  7. 性能考虑与副作用
  8. 总结与未来展望

1. 引言:数据验证的重要性概述

数据验证不仅是确保用户输入正确性的手段,也是维护系统稳定性、数据一致性和安全性的重要措施。

2. 数据验证的基本概念

数据验证是指在数据被处理或存储之前,对其进行检查以确保数据符合预定义的规则。验证可以包括:

  • 格式验证:确保数据符合预期的格式(如邮箱、电话号码)。
  • 业务规则验证:确保数据符合特定的业务逻辑(如用户唯一性)。

3. 数据验证的层次

前端验证

前端验证通常通过JavaScript进行,能够提供即时反馈,减少无效请求。这种验证可以捕捉一些基本错误,但并不足以替代后端验证。

后端验证

后端验证是确保数据在被处理前进行全面检查的关键。它可以防止不合法的数据通过API提交到服务器,并对业务逻辑进行严格控制。

4. 数据验证的标准做法

在Java中,采用Java Bean Validation(JSR 380)是进行数据验证的标准方法。该规范支持一系列内置的校验注解,如@NotNull@Email@Size等。

  1. 注解驱动:通过在Bean类的属性上使用注解定义校验规则。
  2. 统一管理:所有校验逻辑集中于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,结合自定义注解和统一处理机制,能够有效提高系统的稳定性与数据质量。

在这里插入图片描述

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

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

相关文章

物理学基础精解【40】

文章目录 矢量积矢量积&#xff08;又称叉积、外积&#xff09;的几何意义一、面积表示二、垂直性三、方向性四、应用实例五、数学表达 矢量积&#xff08;叉积&#xff09;的坐标表示法矢量积的坐标表示法的几何意义矢量积的性质矢量积的应用 矢量积&#xff08;又称叉积、外积…

Linux——k8s组件

kubernetes 使用1.31.1 版本搭建集群核心组件&#xff0c;选择flannel 网络插件为整体集群的运行提供网络通信功能。 flannel 网络插件 kube-flannel kube-flannel-ds-9fgml 1/1 Running 1 (18m ago) 2d21h kube-flannel kube-flannel-ds-ghwbq …

<<迷雾>> 第 3 章 怎样才能让机器做加法 示例电路

全加器示意图 info::操作说明 鼠标单击开关切换开合状态 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjdmw-examples/assets/circuit/cyjsjdmw-ch03-01-full-adder.txt 原图 由3个全加器组成的3比特加法机 info::操作说明…

Linux——pod的调度

pod的调度 控制器: rc/rs 副本数量控制器 主要保证pod的数量符合管理员要求&#xff0c;并不会对pod进行额外的管理 以下三种控制器&#xff0c;本质上是服务控制器。具备以下特性&#xff1a; 副本数量的控制服务的滚动更新&#xff08;更新pod&#xff09;支持更新失…

基于springboot vue 投票系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

基于51单片机的2路电压采集proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1oNOJJv78ecfWZkdlMyhNVQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

Linux:LCD驱动开发

目录 1.不同接口的LCD硬件操作原理 应用工程师眼中看到的LCD 1.1像素的颜色怎么表示 ​编辑 1.2怎么把颜色发给LCD 驱动工程师眼中看到的LCD 统一的LCD硬件模型 8080接口 TFTRGB接口 什么是MIPI Framebuffer驱动程序框架 怎么编写Framebuffer驱动框架 硬件LCD时序分析…

OpenAI全新多模态内容审核模型上线:基于 GPT-4o,可检测文本和图像

在数字时代&#xff0c;内容安全问题愈发受到重视。9月26日&#xff0c;OpenAI 正式推出了一款全新的多模态内容审核模型&#xff0c;名为 “omni-moderation-latest”。 该模型基于最新的 GPT-4o 技术&#xff0c;能够准确地识别检测有害文本图像。这一更新将为开发者提供强大…

Java | Leetcode Java题解之第445题两数相加II

题目&#xff1a; 题解&#xff1a; class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {Deque<Integer> stack1 new ArrayDeque<Integer>();Deque<Integer> stack2 new ArrayDeque<Integer>();while (l1 ! null) {stack1.…

AI Agent应用出路到底在哪?

1 Agent/Function Call 的定义 Overview of a LLM-powered autonomous agent system&#xff1a; Agent学会调用外部应用程序接口&#xff0c;以获取模型权重中缺失的额外信息&#xff08;预训练后通常难以更改&#xff09;&#xff0c;包括当前信息、代码执行能力、专有信息源…

《深度学习》OpenCV 角点检测、特征提取SIFT 原理及案例解析

目录 一、角点检测 1、什么是角点检测 2、检测流程 1&#xff09;输入图像 2&#xff09;图像预处理 3&#xff09;特征提取 4&#xff09;角点检测 5&#xff09;角点定位和标记 6&#xff09;角点筛选或后处理&#xff08;可选&#xff09; 7&#xff09;输出结果 3、邻域…

深度学习反向传播-过程举例

深度学习中&#xff0c;一般的参数更新方式都是梯度下降法&#xff0c;在使用梯度下降法时&#xff0c;涉及到梯度反向传播的过程&#xff0c;那么在反向传播过程中梯度到底是怎么传递的&#xff1f;结合自己最近的一点理解&#xff0c;下面举个例子简单说明&#xff01; 一、…

Qt开发技巧(九)去掉切换按钮,直接传样式文件,字体设置,QImage超强,巧用Qt的全局对象,信号槽断连,低量数据就用sqlite

继续讲一些Qt开发中的技巧操作&#xff1a; 1.去掉切换按钮 QTabWidget选项卡有个自动生成按钮切换选项卡的机制&#xff0c;有时候不想看到这个烦人的切换按钮&#xff0c;可以设置usesScrollButtons为假&#xff0c;其实QTabWidget的usesScrollButtons属性最终是应用到QTabWi…

衡石分析平台系统管理手册-功能配置之AI 助手集成嵌入指南

AI 助手集成嵌入指南​ 本文档将引导您通过几个简单的步骤&#xff0c;将 AI 助手集成或嵌入到您的系统中。HENGSHI SENSE AI 助手提供了多种集成方式&#xff0c;您可以通过 iframe、JS SDK 或 API 调用等方式将 AI 助手嵌入集成到您的系统中。 1. 通过 iframe 集成​ ifra…

老板最想要的20套模板!基于 VUE 国产开源 IoT 物联网 Web 可视化大屏设计器

如有需求&#xff0c;文末联系小编 Cola-Designer 是一个基于VUE开发&#xff0c;实现拖拽和配置方式生成数据大屏&#xff0c;提供丰富的可视化模板&#xff0c;满足客户业务监控、数据统计、风险预警、地理信息分析等多种业务的展示需求。Cola-Designer 帮助工程师通过图形化…

MySQL - 单表增删改

1. MySQL 概述 MySQL 是一种流行的开源关系型数据库管理系统 (DBMS)&#xff0c;广泛应用于互联网公司和企业开发中。它支持 SQL 语句操作数据&#xff0c;并提供多种版本供选择。 1.1 MySQL 安装和连接 社区版&#xff1a;免费版本&#xff0c;适合开发者使用。商业版&…

sizeof 和 strlen

一 . sizeof 关键字 这个是我们的老朋友了昂&#xff0c;经常都在使用&#xff0c;它是专门用来计算变量所占内存空间大小的&#xff0c;单位是字节&#xff0c;当然&#xff0c;如果我们的操作对象是类型的话&#xff0c;计算的就是类型所创建的变量所占内存的大小&#xff0…

【笔记】神领物流day1.1.13前后端部署【未完】

使用jenkins 前端部署 需要将前端开发的vue进行编译&#xff0c;发布成html&#xff0c;然后通过nginx进行访问&#xff0c;这个过程已经在Jenkins中配置&#xff0c;执行点击发布即可 网址栏输入神领TMS管理系统 (sl-express.com)即可看见启动成功 后端部署看linux 回到Jenki…

25维谛技术面试最常见问题面试经验分享总结(包含一二三面题目+答案)

开头附上工作招聘面试必备问题噢~~包括综合面试题、无领导小组面试题资源文件免费&#xff01;全文干货。 【免费】25维谛技术面试最常见问题面试经验分享总结&#xff08;包含一二三面题目答案&#xff09;资源-CSDN文库https://download.csdn.net/download/m0_72216164/8979…

单调递增/递减栈

单调栈 单调栈分为单调递增栈和单调递减栈 单调递增栈&#xff1a;栈中元素从栈底到栈顶是递增的 单调递减栈&#xff1a;栈中元素从栈底到栈顶是递减的 应用&#xff1a;求解下一个大于x元素或者是小于x的元素的位置 给一个数组&#xff0c;返回一个大小相同的数组&#x…