Updating your Password – 更新你的密码

最后修改: 2015年 4月 6日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick article we’ll implement a simple “Change my own password” functionality available to the user after they register and log in.

在这篇快速文章中,我们将实现一个简单的 “改变我自己的密码 “的功能,在用户注册和登录后可以使用。

2. Client Side – Change My Password Page

2.客户端 – 更改我的密码页面

Let’s take a look at the very simple client side page:

让我们看一下非常简单的客户端页面。

<html>
<body>
<div id="errormsg" style="display:none"></div>
<div>
    <input id="oldpass" name="oldpassword" type="password" />
    <input id="pass" name="password" type="password" />
    <input id="passConfirm" type="password" />              
    <span id="error" style="display:none">Password mismatch</span>
                    
   <button type="submit" onclick="savePass()">Change Password</button>
</div>
 
<script src="jquery.min.js"></script>
<script type="text/javascript">

var serverContext = [[@{/}]];
function savePass(){
    var pass = $("#pass").val();
    var valid = pass == $("#passConfirm").val();
    if(!valid) {
      $("#error").show();
      return;
    }
    $.post(serverContext + "user/updatePassword",
      {password: pass, oldpassword: $("#oldpass").val()} ,function(data){
        window.location.href = serverContext +"/home.html?message="+data.message;
    })
    .fail(function(data) {
        $("#errormsg").show().html(data.responseJSON.message);
    });
}
</script> 
</body>
</html>

3. Update User Password

3.更新用户密码

Let’s now implement the server side operation as well:

现在我们也来实现服务器端的操作。

@PostMapping("/user/updatePassword")
@PreAuthorize("hasRole('READ_PRIVILEGE')")
public GenericResponse changeUserPassword(Locale locale, 
  @RequestParam("password") String password, 
  @RequestParam("oldpassword") String oldPassword) {
    User user = userService.findUserByEmail(
      SecurityContextHolder.getContext().getAuthentication().getName());
    
    if (!userService.checkIfValidOldPassword(user, oldPassword)) {
        throw new InvalidOldPasswordException();
    }
    userService.changeUserPassword(user, password);
    return new GenericResponse(messages.getMessage("message.updatePasswordSuc", null, locale));
}

Notice how the method is secured via the @PreAuthorize annotation, since it should only accessible to logged in users.

请注意该方法是如何通过@PreAuthorize注解来保证安全的,因为它应该只被登录的用户访问

4. API Tests

4.API测试

Finally, let’s consume the API with some API tests to make sure everything is working fine; we’ll start with the simple configuration of the test and the data initialization:

最后,让我们用一些API测试来消耗API,以确保一切工作正常;我们将从测试的简单配置和数据初始化开始。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(
  classes = { ConfigTest.class, PersistenceJPAConfig.class }, 
  loader = AnnotationConfigContextLoader.class)
public class ChangePasswordApiTest {
    private final String URL_PREFIX = "http://localhost:8080/"; 
    private final String URL = URL_PREFIX + "/user/updatePassword";
    
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    FormAuthConfig formConfig = new FormAuthConfig(
      URL_PREFIX + "/login", "username", "password");

    @BeforeEach
    public void init() {
        User user = userRepository.findByEmail("test@test.com");
        if (user == null) {
            user = new User();
            user.setFirstName("Test");
            user.setLastName("Test");
            user.setPassword(passwordEncoder.encode("test"));
            user.setEmail("test@test.com");
            user.setEnabled(true);
            userRepository.save(user);
        } else {
            user.setPassword(passwordEncoder.encode("test"));
            userRepository.save(user);
        }
    }
}

Now – let’s try to change password for a logged in user:

现在–让我们尝试为一个已登录的用户修改密码

@Test
public void givenLoggedInUser_whenChangingPassword_thenCorrect() {
    RequestSpecification request = RestAssured.given().auth()
      .form("test@test.com", "test", formConfig);

    Map<String, String> params = new HashMap<String, String>();
    params.put("oldpassword", "test");
    params.put("password", "newtest");

    Response response = request.with().params(params).post(URL);

    assertEquals(200, response.statusCode());
    assertTrue(response.body().asString().contains("Password updated successfully"));
}

Next – let’s try to change password given a wrong old password:

接下来–让我们试着改变密码给错的旧密码

@Test
public void givenWrongOldPassword_whenChangingPassword_thenBadRequest() {
    RequestSpecification request = RestAssured.given().auth()
      .form("test@test.com", "test", formConfig);

    Map<String, String> params = new HashMap<String, String>();
    params.put("oldpassword", "abc");
    params.put("password", "newtest");

    Response response = request.with().params(params).post(URL);

    assertEquals(400, response.statusCode());
    assertTrue(response.body().asString().contains("Invalid Old Password"));
}

Finally – let’s try to change password without authentication:

最后–让我们尝试在没有认证的情况下更改密码

@Test
public void givenNotAuthenticatedUser_whenChangingPassword_thenRedirect() {
    Map<String, String> params = new HashMap<String, String>();
    params.put("oldpassword", "abc");
    params.put("password", "xyz");

    Response response = RestAssured.with().params(params).post(URL);

    assertEquals(302, response.statusCode());
    assertFalse(response.body().asString().contains("Password updated successfully"));
}

Note how – for each test – we’re providing a FormAuthConfig to handle the authentication.

请注意,对于每个测试,我们都提供一个FormAuthConfig来处理认证。

We’re also resetting the password via init() to make sure we use the correct password before test.

我们还通过init()重设密码,以确保我们在测试前使用正确的密码。

5. Conclusion

5.结论

And that’s a wrap – a straightforward way to allow the user to change their own password after registering and logging into the application.

这就是一个总结–一个允许用户在注册和登录应用程序后改变自己的密码的直接方法。

The full implementation of this tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

本教程的完整实现可以在github 项目中找到 – 这是一个基于 Eclipse 的项目,因此应该很容易导入并按原样运行。

« Previous

Registration – Password Strength and Rules