Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions spring-security-login-and-registration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@
<scope>test</scope>
</dependency>

<!-- Password Validation -->
<dependency>
<groupId>org.passay</groupId>
<artifactId>passay</artifactId>
<version>1.0</version>
</dependency>


<!-- Spring Data JPA dependencies -->
<dependency>
<groupId>org.springframework.data</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ public interface IUserService {
User getUserByID(long id);

void changeUserPassword(User user, String password);

boolean checkIfValidOldPassword(User user, String password);
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
package org.baeldung.persistence.service;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.baeldung.validation.PasswordMatches;
import org.baeldung.validation.ValidEmail;
import org.hibernate.validator.constraints.NotEmpty;
import org.baeldung.validation.ValidPassword;

@PasswordMatches
public class UserDto {
@NotNull
@NotEmpty
@Size(min = 1)
private String firstName;

@NotNull
@NotEmpty
@Size(min = 1)
private String lastName;

@NotNull
@NotEmpty
@ValidPassword
private String password;

@NotNull
@NotEmpty
@Size(min = 1)
private String matchingPassword;

@ValidEmail
@NotNull
@NotEmpty
@Size(min = 1)
private String email;

public String getEmail() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public void changeUserPassword(final User user, final String password) {
repository.save(user);
}

@Override
public boolean checkIfValidOldPassword(final User user, final String oldPassword) {
return passwordEncoder.matches(oldPassword, user.getPassword());
}

private boolean emailExist(final String email) {
final User user = repository.findByEmail(email);
if (user != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class AuthenticationFailureListener implements ApplicationListener<Authen

public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) {
WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails();
loginAttemptService.loginFailed(auth.getRemoteAddress());
if (auth != null) {
loginAttemptService.loginFailed(auth.getRemoteAddress());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class AuthenticationSuccessEventListener implements ApplicationListener<A

public void onApplicationEvent(AuthenticationSuccessEvent e) {
WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails();
loginAttemptService.loginSucceeded(auth.getRemoteAddress());
if (auth != null) {
loginAttemptService.loginSucceeded(auth.getRemoteAddress());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/successRegister.html");
registry.addViewController("/forgetPassword.html");
registry.addViewController("/updatePassword.html");
registry.addViewController("/changePassword.html");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.baeldung.validation;

import java.util.Arrays;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.passay.DigitCharacterRule;
import org.passay.LengthRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RuleResult;
import org.passay.SpecialCharacterRule;
import org.passay.UppercaseCharacterRule;
import org.passay.WhitespaceRule;

import com.google.common.base.Joiner;

public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {

@Override
public void initialize(final ValidPassword arg0) {

}

@Override
public boolean isValid(final String password, final ConstraintValidatorContext context) {
final PasswordValidator validator = new PasswordValidator(Arrays.asList(new LengthRule(8, 30), new UppercaseCharacterRule(1), new DigitCharacterRule(1), new SpecialCharacterRule(1), new WhitespaceRule()));
final RuleResult result = validator.validate(new PasswordData(password));
if (result.isValid()) {
return true;
}
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(Joiner.on("\n").join(validator.getMessages(result))).addConstraintViolation();
return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.baeldung.validation;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = PasswordConstraintValidator.class)
@Target({ TYPE, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface ValidPassword {

String message() default "Invalid Password";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.baeldung.persistence.service.UserDto;
import org.baeldung.registration.OnRegistrationCompleteEvent;
import org.baeldung.validation.EmailExistsException;
import org.baeldung.web.error.InvalidOldPasswordException;
import org.baeldung.web.error.UserAlreadyExistException;
import org.baeldung.web.error.UserNotFoundException;
import org.baeldung.web.util.GenericResponse;
Expand Down Expand Up @@ -133,7 +134,6 @@ public GenericResponse resetPassword(final HttpServletRequest request, @RequestP
final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
final SimpleMailMessage email = constructResetTokenEmail(appUrl, request.getLocale(), token, user);
mailSender.send(email);

return new GenericResponse(messages.getMessage("message.resetPasswordEmail", null, request.getLocale()));
}

Expand Down Expand Up @@ -168,6 +168,19 @@ public GenericResponse savePassword(final Locale locale, @RequestParam("password
return new GenericResponse(messages.getMessage("message.resetPasswordSuc", null, locale));
}

// change user password

@RequestMapping(value = "/user/updatePassword", method = RequestMethod.POST)
@ResponseBody
public GenericResponse changeUserPassword(final Locale locale, @RequestParam("password") final String password, @RequestParam("oldpassword") final String oldPassword) {
final 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));
}

// NON-API

private final SimpleMailMessage constructResendVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.baeldung.web.error;

public final class InvalidOldPasswordException extends RuntimeException {

private static final long serialVersionUID = 5861310537366287163L;

public InvalidOldPasswordException() {
super();
}

public InvalidOldPasswordException(final String message, final Throwable cause) {
super(message, cause);
}

public InvalidOldPasswordException(final String message) {
super(message);
}

public InvalidOldPasswordException(final Throwable cause) {
super(cause);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public RestResponseEntityExceptionHandler() {

// 400
@Override
protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
protected ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
logger.error("400 Status Code", ex);
final BindingResult result = ex.getBindingResult();
final GenericResponse bodyOfResponse = new GenericResponse(result.getFieldErrors(), result.getGlobalErrors());
Expand All @@ -44,6 +44,13 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgume
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}

@ExceptionHandler({ InvalidOldPasswordException.class })
public ResponseEntity<Object> handleInvalidOldPassword(final RuntimeException ex, final WebRequest request) {
logger.error("400 Status Code", ex);
final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.invalidOldPassword", null, request.getLocale()), "InvalidOldEmail");
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}

// 404
@ExceptionHandler({ UserNotFoundException.class })
public ResponseEntity<Object> handleUserNotFound(final RuntimeException ex, final WebRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ message.accountVerified=Your account verified successfully
message.resetPasswordSuc=Password reset successfully
message.resetYourPassword=Reset your password
message.resetPasswordEmail=You should receive an Password Reset Email shortly
message.error=Error Occurred
message.error=Error Occurred
message.updatePasswordSuc=Password updated successfully
message.changePassword=Change Password
message.invalidOldPassword=Invalid Old Password
label.user.newPassword=New Password
label.user.oldPassword=Old Password
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ message.accountVerified=Su cuenta verificada con
message.resetPasswordSuc=Contrase�a reajusta correctamente
message.resetYourPassword=Restablecer su contrase�a
message.resetPasswordEmail=Te enviaremos un correo electr�nico para restablecer su contrase�a
message.error=Se produjo un error
message.error=Se produjo un error
message.updatePasswordSuc=Contrase�a actualizado correctamente
message.changePassword=Cambiar La Contrase�a
message.invalidOldPassword=Inv�lida contrase�a antigua
label.user.newPassword=Nueva Contrase�a
label.user.oldPassword=Contrase�a Anterior
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
uri="http://www.springframework.org/security/tags"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<html>

<head>
<link href="<c:url value="/resources/bootstrap.css" />" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title><spring:message code="label.pages.home.title"></spring:message></title>
</head>
<body>
<div class="container">
<div class="span12">
<sec:authorize ifNotGranted="WRITE_PRIVILEGE">
<spring:message code="message.unauth"></spring:message>
</sec:authorize>
<sec:authorize ifAnyGranted="WRITE_PRIVILEGE">
<H1>
<spring:message code="label.pages.admin.message"></spring:message>
</H1>
</sec:authorize>
<a href="<c:url value="/j_spring_security_logout" />"><spring:message
code="label.pages.logout"></spring:message></a> <a
href="<c:url value="/home.html" />"><spring:message
code="label.pages.home.title"></spring:message></a>
</div>
</div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand"href="<c:url value="/home.html" />"><spring:message code="label.pages.home.title"></spring:message></a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="<c:url value="/j_spring_security_logout" />"><spring:message code="label.pages.logout"></spring:message></a> </li>
</ul>
</div>
</nav>

<div class="container">
<sec:authorize ifNotGranted="WRITE_PRIVILEGE">
<spring:message code="message.unauth"></spring:message>
</sec:authorize>
<sec:authorize ifAnyGranted="WRITE_PRIVILEGE">
<h1>
<spring:message code="label.pages.admin.message"></spring:message>
</h1>
</sec:authorize>
</div>
</body>
</html>
</html>
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
uri="http://www.springframework.org/security/tags"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<fmt:setBundle basename="messages" />
<%@ page session="true"%>
<html>
<head>
<link href="<c:url value="/resources/bootstrap.css" />" rel="stylesheet">
<title><spring:message
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title><spring:message
code="label.badUser.title"></spring:message></title>
</head>
<body>
<h1>
<div class="alert alert-error">
${param.message}
<div class="container">
<h1 class="alert alert-danger">
${param.message}
</h1>
<br>
<a href="<c:url value="/registration.html" />"><spring:message
<a class="btn btn-default" href="<c:url value="/registration.html" />"><spring:message
code="label.form.loginSignUp"></spring:message></a>

<c:if test="${param.expired}">
<br>
<h1>${label.form.resendRegistrationToken}</h1>
<button onclick="resendToken()">
<spring:message code="label.form.resendRegistrationToken"></spring:message>
<spring:message code="label.form.resendRegistrationToken"></spring:message>
</button>


<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
function resendToken(){
$.get("<c:url value="/user/resendRegistrationToken"><c:param name="token" value="${param.token}"/></c:url>", function(data){
window.location.href = "<c:url value="/login.html"></c:url>" + "?message=" + data.message;
$.get("<c:url value="/user/resendRegistrationToken"><c:param name="token" value="${param.token}"/></c:url>", function(data){
window.location.href = "<c:url value="/login.html"></c:url>" + "?message=" + data.message;
})
.fail(function(data) {
if(data.responseJSON.error.indexOf("MailError") > -1)
Expand All @@ -50,5 +49,6 @@ $(document).ajaxStart(function() {
});
</script>
</c:if>
</div>
</body>
</html>
Loading