作者:Eugen Paraschiv
转载自公众号:stackgc
1、概述
在本文中,我们将使用 Spring Security 实现一个基本的注册流程。该示例是建立在上一篇文章的基础上。
本文目标是添加一个完整的注册流程,可以注册用户、验证和持久化用户数据。
2、注册页面
首先,让我们实现一个简单的注册页面,有以下字段:
- name
- emal
- password
下例展示了一个简单的 registration.html 页面:
示例 2.1
1 | 复制代码<html> |
3、User DTO 对象
我们需要一个数据传输对象(Data Transfer Object,DTO)来将所有注册信息封装起来发送到 Spring 后端。当创建和填充 User 对象时,DTO 对象应该要有之后需要用到的所有信息:
1 | 复制代码public class UserDto { |
注意,我们在 DTO 对象的字段上使用了标准的 javax.validation 注解。稍后,我们还将实现自定义验证注解来验证电子邮件地址格式和确认密码。(见第 5 节)
4、注册控制器
登录页面上的注册链接跳转到 registration 页面。该页面的后端位于注册控制器中,其映射到 /user/registration:
示例 4.1 — showRegistration 方法
1 | 复制代码@RequestMapping(value = "/user/registration", method = RequestMethod.GET) |
当控制器收到 /user/registration 请求时,它会创建一个新的 UserDto 对象,绑定它并返回注册表单,很简单。
5、验证注册数据
让我们看看控制器在注册新账户时所执行的验证:
- 所有必填字段都已填写(无空白字段或 null 字段)
- 电子邮件地址有效(格式正确)
- 密码确认字段与密码字段匹配
- 帐户不存在
5.1、内置验证
对于简单的检查,我们在 DTO 对象上使用开箱即用的 bean 验证注解 — @NotNull、@NotEmpty 等。
为了触发验证流程,我们只需使用 @Valid 注解对控制器层中的对象进行标注:
1 | 复制代码public ModelAndView registerUserAccount( |
5.2、使用自定义验证检查电子邮件有效性
让我们来验证电子邮件地址并确保其格式正确。我们要创建一个自定义的验证器,以及一个自定义验证注解,将它命名为 @ValidEmail。
要注意的是,我们使用的是自定义注解,而不是 Hibernate 的 @Email,因为 Hibernate 会将内网地址(如 myaddress@myserver)视为有效的电子邮箱地址格式(见 Stackoverflow 文章),这并不好。
以下是电子邮件验证注解和自定义验证器:
例 5.2.1 — 用于电子邮件验证的自定义注解
1 | 复制代码@Target({TYPE, FIELD, ANNOTATION_TYPE}) |
请注意,我们定义了 FIELD 级别注解。
例 5.2.2 — 自定义 EmailValidator:
1 | 复制代码public class EmailValidator |
之后在 UserDto 实现上使用新的注解:
1 | 复制代码@ValidEmail |
5.3、密码确认使用自定义验证
我们还需要一个自定义注解和验证器来确保 password 和 matchingPassword 字段匹配:
例 5.3.1 — 验证密码确认的自定义注解
1 | 复制代码@Target({TYPE,ANNOTATION_TYPE}) |
请注意,@Target 注解指定了这是一个 TYPE 级别注解。因为我们需要整个 UserDto 对象来执行验证。
下面为由此注解调用的自定义验证器:
例 5.3.2 — PasswordMatchesValidator 自定义验证器
1 | 复制代码public class PasswordMatchesValidator |
将 @PasswordMatches 注解应用到 UserDto 对象上:
1 | 复制代码@PasswordMatches |
5.4、检查帐户是否存在
我们要执行的第四项检查:验证电子邮件帐户是否存在于数据库中。
这是在表单验证之后执行的,并且是在 UserService 实现的帮助下完成的。
例 5.4.1 — 控制器的 createUserAccount 方法调用 UserService 对象
1 | 复制代码@RequestMapping(value = "/user/registration", method = RequestMethod.POST) |
例 5.4.2 — UserService 检查重复的电子邮件
1 | 复制代码@Service |
UserService 使用 UserRepository 类来检查指定的电子邮件地址的用户是否已经存在于数据库中。
持久层中 UserRepository 的实际实现与当前文章无关。你可以使用 Spring Data 来快速生成资源库(repository)层。
6、持久化数据和完成表单处理
最后,在控制器层实现注册逻辑:
例 6.1.1 — 控制器中的 RegisterAccount 方法
1 | 复制代码@RequestMapping(value = "/user/registration", method = RequestMethod.POST) |
上面的代码中需要注意以下事项:
- 控制器返回一个 ModelAndView 对象,它可将模型数据(user)传入到要绑定的视图中。
- 如果在验证时发生错误,控制器将重定向到注册表单。
- createUserAccount 方法调用 UserService 持久化数据 。我们将在下一节讨论 UserService 实现
7、UserService - 注册操作
让我们来完成 UserService 中注册操作实现:
例 7.1 — IUserService 接口
1 | 复制代码public interface IUserService { |
例 7.2 — UserService 类
1 | 复制代码@Service |
8、加载 User Detail 用于安全登录
在之前的文章中,登录使用了硬编码的凭据。现在让我们修改一下,使用新注册的用户信息和凭证。我们将实现一个自定义的 UserDetailsService 来检查持久层的登录凭据。
8.1、自定义 UserDetailsService
从自定义的 user detail 服务实现开始:
1 | 复制代码@Service |
8.2、启用新的验证提供器
为了在 Spring Security 配置中启用新的用户服务,我们只需要在 authentication-manager 元素内添加对 UserDetailsService 的引用,并添加 UserDetailsService bean:
例子 8.2 — 验证管理器和 UserDetailsService
1 | 复制代码<authentication-manager> |
或者,通过 Java 配置:
1 | 复制代码@Autowired |
9、结论
终于完成了 —— 一个由 Spring Security 和 Spring MVC 实现的几乎可用于准生产环境的注册流程。在后续文章中,我们将通过验证新用户的电子邮件来探讨新注册帐户的激活流程。
该 Spring Security REST 教程的实现源码可在 GitHub 项目上获取 —— 这是一个 Eclipse 项目。
原文示例代码
本文转载自: 掘金