1. 概述
在本教程中,我将解释如何使用JWT(JSON Web Tokens)实现生产就绪的基于令牌的REST API身份验证。我们将进一步使用这些令牌来标识我们在API的HTTP请求中的操作用户。对于本教程,我们将使用MongoDB来持久化我们的用户数据,你可以选择任何你喜欢的数据库。
2. 什么是JWT?
JSON Web Token(JWT)是一个编码字符串,我们将在这种情况下用它来标识我们的用户。 JWT由三部分组成,由句点(“.”)分隔:
- 头部:它包含签名算法,例如SHA256。
- 载荷:它包含我们的用户数据。
- 签名:为了验证消息在传输过程中未被更改,使其更加安全。
将所有三个组合在一起,我们的JWT看起来像这样xxxxx.yyyyy.zzzzz
。要了解有关JWT的更多信息,请访问- https://jwt.io/
3. 项目初始化
我们将使用Spring Initiailizr来初始化我们的Spring Boot项目。为了方便起见,我添加了5个依赖项,你可以根据项目需求进行微调。
生成并将项目导入你喜欢的IDE。还要记得在application.properties
文件中添加数据库属性。
spring.data.mongodb.database=your_db_name_here spring.data.mongodb.port=27017
4. 其他依赖项
你将不得不添加以下依赖项以在项目中使用JWT
。 commons-lang3
是可选的,我个人使用它的各种实用程序类。
对于基于maven的项目:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency><dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency><dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency><dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
对于基于gradle的项目:
dependencies {
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2',
'io.jsonwebtoken:jjwt-jackson:0.11.2',
'org.apache.commons:commons-lang3:3.0'
}
5. 项目结构
我们将遵循MVC模式,请参阅以下项目结构。
6. 配置
在WebSecurityConfig.java
中,我们将通过扩展WebSecurityConfigurerAdapter
类来修改默认的spring security功能。在这里,我们将定义我们的HTTP请求过滤器和未经身份验证的用户的默认响应。它将作为所有HTTP请求的中间件。
在上面的configure(HttpSecurity httpSecurity)
方法中,我们已经定义了允许以/auth
路由开头的所有请求,这是我们将添加我们的身份验证控制器的地方。如果请求未经授权,我们的API将抛出一个401
错误消息。
7. 请求过滤器
在JwtRequestFilter.java
中,我们将定义我们在前一章节中提到的API中间件中的请求过滤器。为此,我们将扩展OncePerRequestFilter
,Spring保证它仅针对给定请求执行一次。
在这个doFilterInternal()
方法中,我们将从请求头中获取JWT令牌并处理它,通过验证并从令牌的有效负载中获取用户名。进一步地,如果令牌有效,我们将从数据库中获取用户并将其添加到SecurityContextHolder
中,我们可以在任何服务中进一步使用它来执行各种与用户相关的操作。
在JwtTokenUtil.java
中,我们将执行所有JWT令牌相关的操作,例如生成新令牌和验证给定令牌。
8. 模型和存储库
我们将在这里使用Lombok框架快速创建我们的User.java
模型。它完全是可选的,但这是我定义模型类的最喜欢的方式。毕竟,生命太短暂,无法编写getter和setter。
我们将编写我们的UserRepository.java
接口,并定义一个方法来从用户名中获取用户详细信息。
9. UserDetailsService
在JwtUserDetailsService.java
类中,我们将通过实现UserDetailsService
接口来自定义默认的spring security获取用户的方式。
10. 控制器
最后但并非最不重要的是,我们将定义控制器以与我们的API通信。
AuthenticationController.java
将处理用户登录和注册。在这两个路由中,我们将生成JWT令牌并将其发送到用户的响应中。
响应我们注册请求的示例:
你可以将响应中的此令牌保存在客户端(反应式Web或移动应用程序)的本地存储中,并稍后在API的受保护路由中使用此令牌。如果我们提供无效凭据给我们的登录请求,我们将获得带有错误代码401的响应:
现在是时候实际使用我们的JWT令牌来标识与HTTP请求相关联的用户了。以下代码段将帮助你在项目的任何地方获取经过身份验证的用户:
Authentication authentication = SecurityContextHolder
.getContext().getAuthentication();
String username = authentication.getName();
为测试,我们将定义UserController.java
。在这里,你可以获取我们在请求过滤器中添加的用户SecurityContextHolder
。当我们在授权头中发送新创建的JWT令牌时,我们将获得以下适当的响应:
11. 结论
我们看到了如何为REST API实现基于令牌的身份验证以及各种神奇的框架来使生活更轻松。
本教程的完整代码已提交到我的Github存储库。不要忘记点击星标按钮:p
感谢你阅读本文,请在评论区提供宝贵的反馈。
原始发布在 https://blog.iamprafful.com.
评论(0)