Vert.x,认证与授权 - HTTP基本认证

news2024/11/26 2:40:49

几乎所有的线上系统都离不开认证和授权,Vert.x auth相关组件提供了丰富(Session,JTW, OAuth,…),便捷的认证和授权支持。

当前,使用最多是Web应用,所以在后续讨论中,都是关于Vert.x auth在Web应用(Vertx web)中的使用。

基本概念

认证与授权

认证/鉴权(Authentication) 是指验证用户的身份。// Tells who the user is

  • 确认用户或系统的身份,以确保他们是所声称的那个人或系统。
  • 认证通常通过用户名和密码、数字证书、生物识别(如指纹或面部识别)等方式进行。
  • 例如,当你输入用户名和密码登录到某个应用程序时,系统会检查你的凭证以确认你的身份。

授权(Authorization) 授权是在认证之后进行的,它决定已认证用户可以访问哪些资源或执行哪些操作。// Tells what the user is allowed to do

  • 授权通常在认证之后,当在服务器端的身份确认后,会获取对应用户在服务器端的权限,在执行有权限要求的操作前,先用户的权限进行检查。
  • 授权的过程涉及设置权限和访问控制,比如数据库的读取、写入权限,或是特定文件夹的访问权限。
  • 例如,在同一个应用程序中,普通用户可能只能查看信息,而管理员则可以编辑和删除信息。

认证方式

参考来源: https://developer.baidu.com/article/details/3133306

有状态身份验证( Session-Cookie Based Authentication)

有状态身份验证,也称为会话认证,指的是服务端需要记录每次会话的客户端信息以识别客户端身份。常见的有状态认证方式包括使用cookie和session。当用户登录后,服务端会将登录信息保存在session中,并给用户分配一个唯一的session ID。随后,每次用户请求时,都需要携带该session ID,以便服务端能够识别和验证用户身份。

无状态身份验证 (Token-Based Authentication)

无状态身份验证,也称为令牌认证,是一种不依赖服务端会话的认证方式。在无状态认证中,服务端不需要记录用户的会话信息。用户通过首次认证后,服务端会生成一个令牌(通常使用JSON Web Token,简称JWT),并将其传递给客户端。客户端在后续请求中携带该令牌进行身份验证。

有状态和无状态身份验证各有优缺点,选择合适的认证方式取决于具体需求和应用场景。 有状态认证适用于需要个性化配置和复杂权限控制的Web应用,而无状态认证适用于对性能和扩展性要求较高的场景,如微服务架构、API网关等。此外,无状态认证也适用于跨域应用和单点登录的场景。

Vert.x auth使用概述

通用认证和授权(vertx-auth-common)组件提供了用于身份验证和授权的接口,是Vert.x auth的基础,要在项目中使用,必须先引入依赖:

<dependency>
	<groupId>io.vertx</groupId>
	<artifactId>vertx-auth-common</artifactId>
	<version>4.5.10</version>
</dependency>

要使用Vert.x auth我们需要实现的两个核心接口是AuthenticationProvider和User。AuthenticationProvider用于告诉系统如何进行身份认证,而User实例是用户对应在服务器中的权限的载体(authorisation of users),是AuthorizationProvider接口方法authenticate返回的(异步)结果。

归纳来说: AuthenticationProvider的authenticate对输入的信息进行身份认证,如果认证通过后,返回对应用户在服务器端的权限User(异步结果),如果不通过返回失败结果。先有个概念,后续将通过案例来具体说明。

HTTP基本认证(Http Basic Auth

HTTP基本认证(HTTP Basic Access Authentication )是一种用于网络协议的简单认证方式,这种方法通常用于控制对特定资源的访问。在HTTP基本认证中,服务器会向未经认证的请求返回一个401 Unauthorized状态码,并在响应头中包含一个’WWW-Authenticate’字段,提示客户端需要提供认证信息。客户端随后会在请求头中包含一个Authorization字段,其中包含了经过Base64编码的用户名和密码。

HTTP基本认证中的用户名和密码是以明文形式(经过Base64编码)传输的,因此不建议在不安全的网络中使用。为了保护认证信息的安全,应该在HTTPS/TLS的保护下使用HTTP基本认证。

HTTP基本认证不安全,目前很少使用。拿来讨论,是因为简单,便于理解认证与授权的编写。假设有3个页面:

- page1.html: 不需要身份认证既可以访问;
- page2.html: 所有认证用户都可以访问;
- page3.html: 仅admin角色可以访问;

下面通过Vert.x Auth实现上述需求。

public class BasicAccessAuth {
	private static final Logger LOGGER = Logger.getLogger(BasicAccessAuth.class.getName());

	public static void main(String[] args) {

		// 模拟服务器存储的用户密码,实际场景这些信息可以存储在数据库。
		HashMap<String, String> users = new HashMap<>();
		users.put("admin", "password");
		users.put("user", "password");

		Vertx vertx = Vertx.vertx();
		HttpServer server = vertx.createHttpServer();
		Router router = Router.router(vertx);

		// 步骤1: 创建一个authProvider实例,这里用了匿名类,实际编码时可以编写一个实现AuthenticationProvider接口的类,并实例化。
		AuthenticationProvider authProvider = new AuthenticationProvider() {
			// 认证处理器,异步方法,结果返回一个User结果。
			@Override
			public void authenticate(JsonObject credentials, Handler<AsyncResult<User>> resultHandler) {
				LOGGER.info("input credentials = " + credentials.encode()); // encodePrettily
				// 通过密码进行身份认证
				String username = credentials.getString("username");
				String password = credentials.getString("password");
				if (users.containsKey(username) && users.get(username).equals(password)) {
					// 通过了身份认证,根据用户在服务器中的权限创建一个User实例。
					// 我们模拟了一个简单的权限,角色。
					// 权限根据实际来设计,例如可以基于角色,也可以设计成基于权限,如: 某个路径(path)设计权限位(rwx) ...
					// 实际场景中,用户对应的权限通常存储在数据库中。
					// User实例是用户对应权限的载体。
					String role = username.equalsIgnoreCase("admin") ? "admin" : "user";
					JsonObject principal = new JsonObject();
					principal.put("username", username);

					// 属性信息
					JsonObject attributes = new JsonObject();
					attributes.put("role", role);
					// 步骤2: 根据用户对应权限实例化User做为认证结果。
					// 这里权限比较简单,使用了Vert.x自带的UserImpl,实际编码时可以编写一个实现User接口的类。
					User user = new UserImpl(principal, attributes);
					resultHandler.handle(Future.succeededFuture(user));
				} else {
					resultHandler.handle(Future.failedFuture("身份认证失败。"));
				}
			}
		};
		
		// '/hr/page1.html'直接返回静态页面,不使用基本认证。
		// 原理: 因为该路由比认证处理器的路由先加入router,所以优先级高,关于路由优先级与多路由,可以参考我之前写的文章。
		router.route("/hr/page1.html").handler(ctx -> {
			HttpServerResponse response = ctx.response();
			response.putHeader("Content-Type", "text/html");
			response.sendFile("webroot/page1.html");
		});

		// 步骤3: 创建认证处理器,与对应(需要认证的)路由关联。
		// 处理器可以自己写,也可使用Vertx自带的BasicAuthHandler
		// '/hr/*'路由与BasicAuthHandler绑定,实现访问'/hr/*'都需要进行Http Basic Auth认证。
		BasicAuthHandler basicAuthHandler = BasicAuthHandler.create(authProvider);
		router.route("/hr/*").handler(basicAuthHandler);
		
		router.route("/hr/page3.html").handler(ctx -> {
			// 经过身份认证路由后,认证成功会获取用户授权信息。
			User user = ctx.user();
			if (user != null) {
				// String role = user.attributes().getString("role");
				String role = user.get("role");
				if ("admin" != role) {
					HttpServerResponse response = ctx.response();
					response.setStatusCode(401).setStatusMessage("admin only");
					response.putHeader("Content-Type", "text/html; charset=utf-8");
					response.end("仅admin角色可以访问。");
				}
			}
			ctx.next();
		});
		
		router.route("/hr/*").handler(StaticHandler.create());

		server.requestHandler(router).listen(8080);
	}
}

访问http://127.0.0.1:8080/hr/page1.html,可以正常访问page1.html。
访问http://127.0.0.1:8080/hr/page2.html,会弹出浏览器原生的登录框提示密码登录。
在这里插入图片描述
当通过admin/password或者user/password登录后,可以正常访问page2.html内容。

访问http://127.0.0.1:8080/hr/page3.html,仅当通过admin/password登录时,才能看到page3.html内容,如果使用user用户登录,会提示"仅admin角色可以访问。"

测试时候注意,HTTP基本认证本地cookie会保存密码,无法通过(重启)服务器注销用户,最简单的方法是通过删除cookie方式实现用户注销(切换用户)。
在这里插入图片描述
完整的案例已上传在本文的资源中,感兴趣的可以下载。

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

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

相关文章

kernel32.dll下载地址:如何安全地恢复系统文件

关于从网络上寻找kernel32.dll的下载地址&#xff0c;这通常不是一个安全的做法&#xff0c;而且可能涉及到多种风险。kernel32.dll是Windows操作系统的核心组件之一&#xff0c;负责内存管理、进程和线程管理以及其他关键系统功能。因为kernel32.dll是系统的基础文件&#xff…

IDEA如何给debug断点加上筛选条件判断

前言 我们在使用IDEA开发Java应用时&#xff0c;经常是需要进行代码调试的&#xff0c;这就需要打断点进行操作。但有些时候&#xff0c;我们只希望在符合某种条件的情况下&#xff0c;才去到这个断点&#xff0c;不符合的情况下&#xff0c;直接跳过断点&#xff0c;这其实也…

【linux】线程 (三)

13. 常见锁概念 &#xff08;一&#xff09;了解死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程占有的&#xff0c;且不释放的资源&#xff0c;而处于的一种永久等待状态 &#xff08;二&#xff09;死锁四个必要条件 互斥条件…

深度学习(一)基础:神经网络、训练过程与激活函数(1/10)

深度学习基础&#xff1a;神经网络、训练过程与激活函数 引言&#xff1a; 深度学习作为机器学习的一个子领域&#xff0c;近年来在人工智能的发展中扮演了举足轻重的角色。它通过模仿人脑的神经网络结构&#xff0c;使得计算机能够从数据中学习复杂的模式和特征&#xff0c;…

COLA架构生成DDD项目

1.下载代码 https://github.com/alibaba/COLA 2.执行命令 2.1 shell Linux mvn archetype:generate \-DgroupIdcom.xxc \-DartifactIdcola-springboot-demo \-Dversion0.0.1 \-Dpackagecom.xxc.demo \-DarchetypeArtifactIdcola-framework-archetype-web \-DarchetypeGrou…

我是类(最终版)

文章目录 再看构造函数类型转换static静态成员友元内部类匿名对象对象拷贝时的编译器优化 再看构造函数 本标题的目的是解决如下问题&#xff1a;当实现MyQueue时&#xff0c;我们不需要写默认构造函数&#xff0c;因为编译器会调用Stack的默认构造&#xff0c;但是&#xff0…

01 设计模式-创造型模式-工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。 通过使用工厂模式…

vue 页面导出gif图片 img 导出gif 超简单~

1.首先需要新建一个文件件 新建gif文件夹。这两个文件在文章最后面需要可自提 2.出gif分为两种情况 第一种情况 页面是img标签&#xff0c;直接导出图片作为gif 第二种情况 页面是div标签&#xff0c;需要导出div里面的图片作为gif 2.1页面是img标签&#xff0c;直接导出图…

电脑异常情况总结

文章目录 笔记本无症状息屏黑屏 笔记本无症状息屏黑屏 &#x1f34e; 问题描述&#xff1a; 息屏导致黑屏&#xff1b;依次操作计算机--》右键--》管理--》事件查看器--》Windows日志--》系统&#xff1b;从息屏到异常黑屏之间出现了很多错误&#xff0c;如下&#xff1a;事件…

使用CMake生成动态链接库(.dll和.so)和静态链接库(.lib和.a)的方法

&#xff08;一&#xff09;简介 对于大型软件开发&#xff0c;动态连接库是必不可少的。不仅可以实现模块的封装&#xff0c;而且可以实现软件的热更新&#xff08;即替换windows下的.dll或Linux下的.so文件后直接实现软件更新&#xff0c;无需重新编译&#xff09;。有时也需…

力扣 困难 52.N皇后II

文章目录 题目介绍题解 题目介绍 题解 法一&#xff1a;返回51题N皇后List的长度 法二&#xff1a; class Solution {private int n, ans;private boolean[] onPath, diag1, diag2;public int totalNQueens(int n) {this.n n;onPath new boolean[n];diag1 new boolean[n * …

Standard IO

为了提高可移植性&#xff0c;将通用IO接口经过再封装就形成了标准IO&#xff0c;标准IO不仅适用于Unix环境&#xff0c;也兼容非Unix环境&#xff0c;这也是为什么说我们应该尽可能的使用标准IO&#xff0c;通用IO通过文件描述符fd来与文件交互&#xff0c;为了以示区分&#…

element plus e-table表格中使用多选,当翻页时已选中的数据丢失

摘要&#xff1a; 点击第一页选中两个&#xff0c;再选择第二页&#xff0c;选中&#xff0c;回到第一页&#xff0c;之前选中的要保留&#xff01; element ui table 解决办法&#xff1a; :row-key“getRowKeys” &#xff08;写在el-table中&#xff09; methods中声明 ge…

多一DY4100数字式接地电阻测试仪使用测量方法

接地电阻二线法测量步骤 1、找出一套简易测试线&#xff0c;一根红色两插头线和一根短绿线&#xff1b; 2、找出一根辅助地钉&#xff0c;距离被测接地桩/扁铁约五米远整根打下去&#xff1b; 3、绿线插头接仪器E孔&#xff08;绿色孔&#xff09;&#xff0c;夹子夹需测的接…

ArcGIS002:软件自定义设置

摘要&#xff1a;本文详细介绍安装arcgis10.2后软件自定义设置内容&#xff0c;包括工具条的启用、扩展模块的启用、如何加载项管理器、快捷键设置、样式管理器的使用以及软件常规设置。 一、工具条的启用 依次点击菜单栏【自定义】->【工具条】&#xff0c;根据工作需求勾…

医院信息化与智能化系统(5)

医院信息化与智能化系统(5) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…

【漏洞修复/安全补丁】5.4之前版本通过api/products接口进行sql注入的问题

5.4之前版本&#xff0c;会使用api/products接口的selectId参数进行sql注入 修复办法 1、修改crmeb/app/api/controller/v1/store/StoreProductController.php文件中的lst方法里面的接收参数&#xff0c;修改成下图 如果你的版本没有coupon_category_id参数的话&#xff0c;…

No.19 笔记 | WEB安全 - 任意文件操作详解 part 1

1. 任意文件上传漏洞基础 什么是文件上传功能? 在网站和应用中,我们经常会看到允许用户上传文件的功能,比如: 更换头像:让用户上传自己的照片作为头像发布图片:在社交媒体或论坛上传图片提交文档:在办公系统中上传Word、Excel等文档 这些都是常见的文件上传功能。 任意文…

Kettle9.4支持Clickhouse数据源插件开发以及性能测试

前言 最近业务这边有个指标需要用到大数据这边的列式数据库进行处理&#xff0c;由于kettle不支持clickhouse数据源驱动&#xff0c;这里查了一下网上的相关资料&#xff0c;发现了一些别人开发好的驱动包&#xff0c;下载下来后使用效果不尽人意。总结下来有以下几个问题&…

重生之“我打数据结构,真的假的?”--1.顺序表(无习题)

C语言中的顺序表详细总结 1. 概述 顺序表&#xff08;Sequential List&#xff09;是一种线性数据结构&#xff0c;用于存储具有相同数据类型的一组元素。顺序表采用一段连续的存储空间&#xff0c;使用数组来实现&#xff0c;能够高效地支持随机访问操作。在 C 语言中&#…