Skip to content

Commit d987a9b

Browse files
committed
implement login page back-end
1 parent fb46e41 commit d987a9b

File tree

13 files changed

+453
-14
lines changed

13 files changed

+453
-14
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2424
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
2525
<java.version>1.8</java.version>
26+
<commons-io.version>2.6</commons-io.version>
2627
</properties>
2728

2829
<dependencies>
@@ -50,6 +51,11 @@
5051
<groupId>org.apache.commons</groupId>
5152
<artifactId>commons-lang3</artifactId>
5253
</dependency>
54+
<dependency>
55+
<groupId>commons-io</groupId>
56+
<artifactId>commons-io</artifactId>
57+
<version>${commons-io.version}</version>
58+
</dependency>
5359

5460
<dependency>
5561
<groupId>org.springframework.boot</groupId>
Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package com.taskagile.config;
22

3+
import com.taskagile.web.apis.authenticate.AuthenticationFilter;
4+
import com.taskagile.web.apis.authenticate.SimpleAuthenticationFailureHandler;
5+
import com.taskagile.web.apis.authenticate.SimpleAuthenticationSuccessHandler;
6+
import com.taskagile.web.apis.authenticate.SimpleLogoutSuccessHandler;
37
import org.springframework.context.annotation.Bean;
48
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
59
import org.springframework.security.config.annotation.web.builders.WebSecurity;
610
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
711
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
812
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
913
import org.springframework.security.crypto.password.PasswordEncoder;
14+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
15+
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
16+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
17+
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
1018

1119
@EnableWebSecurity
1220
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@@ -18,17 +26,18 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
1826
protected void configure(HttpSecurity http) throws Exception {
1927
http
2028
.authorizeRequests()
21-
.antMatchers(PUBLIC).permitAll()
22-
.anyRequest().authenticated()
29+
.antMatchers(PUBLIC).permitAll()
30+
.anyRequest().authenticated()
2331
.and()
24-
.formLogin()
25-
.loginPage("/login")
32+
.addFilterAt(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
33+
.formLogin()
34+
.loginPage("/login")
2635
.and()
27-
.logout()
28-
.logoutUrl("/logout")
29-
.logoutSuccessUrl("/login?logged-out")
36+
.logout()
37+
.logoutUrl("/logout")
38+
.logoutSuccessHandler(logoutSuccessHandler())
3039
.and()
31-
.csrf().disable();
40+
.csrf().disable();
3241
}
3342

3443
@Override
@@ -40,4 +49,28 @@ public void configure(WebSecurity web) {
4049
public PasswordEncoder passwordEncoder() {
4150
return new BCryptPasswordEncoder();
4251
}
52+
53+
@Bean
54+
public AuthenticationFilter authenticationFilter() throws Exception {
55+
AuthenticationFilter authenticationFilter = new AuthenticationFilter();
56+
authenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
57+
authenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
58+
authenticationFilter.setAuthenticationManager(authenticationManagerBean());
59+
return authenticationFilter;
60+
}
61+
62+
@Bean
63+
public AuthenticationSuccessHandler authenticationSuccessHandler() {
64+
return new SimpleAuthenticationSuccessHandler();
65+
}
66+
67+
@Bean
68+
public AuthenticationFailureHandler authenticationFailureHandler() {
69+
return new SimpleAuthenticationFailureHandler();
70+
}
71+
72+
@Bean
73+
public LogoutSuccessHandler logoutSuccessHandler() {
74+
return new SimpleLogoutSuccessHandler();
75+
}
4376
}

src/main/java/com/taskagile/domain/application/UserService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import com.taskagile.domain.application.commands.RegistrationCommand;
44
import com.taskagile.domain.model.user.RegistrationException;
5+
import org.springframework.security.core.userdetails.UserDetailsService;
56

6-
public interface UserService {
7+
public interface UserService extends UserDetailsService {
78

89
/**
910
* Register a new user with username, email address, and password.

src/main/java/com/taskagile/domain/application/impl/UserServiceImpl.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
import com.taskagile.domain.common.event.DomainEventPublisher;
66
import com.taskagile.domain.common.mail.MailManager;
77
import com.taskagile.domain.common.mail.MessageVariable;
8-
import com.taskagile.domain.model.user.RegistrationException;
9-
import com.taskagile.domain.model.user.RegistrationManagement;
10-
import com.taskagile.domain.model.user.User;
8+
import com.taskagile.domain.model.user.*;
119
import com.taskagile.domain.model.user.events.UserRegisteredEvent;
10+
import org.springframework.security.core.userdetails.UserDetails;
11+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
1212
import org.springframework.stereotype.Service;
1313
import org.springframework.util.Assert;
14+
import org.springframework.util.StringUtils;
1415

1516
import javax.transaction.Transactional;
1617

@@ -21,13 +22,34 @@ public class UserServiceImpl implements UserService {
2122
private RegistrationManagement registrationManagement;
2223
private DomainEventPublisher domainEventPublisher;
2324
private MailManager mailManager;
25+
private UserRepository userRepository;
2426

2527
public UserServiceImpl(RegistrationManagement registrationManagement,
2628
DomainEventPublisher domainEventPublisher,
27-
MailManager mailManager) {
29+
MailManager mailManager,
30+
UserRepository userRepository) {
2831
this.registrationManagement = registrationManagement;
2932
this.domainEventPublisher = domainEventPublisher;
3033
this.mailManager = mailManager;
34+
this.userRepository = userRepository;
35+
}
36+
37+
38+
@Override
39+
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
40+
if (StringUtils.isEmpty(username)) {
41+
throw new UsernameNotFoundException("No user found");
42+
}
43+
User user;
44+
if (username.contains("@")) {
45+
user = userRepository.findByEmailAddress(username);
46+
} else {
47+
user = userRepository.findByUsername(username);
48+
}
49+
if (user == null) {
50+
throw new UsernameNotFoundException("No user found by `" + username + "`");
51+
}
52+
return new SimpleUser(user);
3153
}
3254

3355
@Override
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.taskagile.domain.model.user;
2+
3+
import org.springframework.security.core.GrantedAuthority;
4+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
5+
import org.springframework.security.core.userdetails.UserDetails;
6+
7+
import java.io.Serializable;
8+
import java.util.Collection;
9+
import java.util.Collections;
10+
import java.util.Objects;
11+
12+
public class SimpleUser implements UserDetails, Serializable {
13+
14+
private static final long serialVersionUID = -7144174657188362966L;
15+
16+
private long userId;
17+
private String username;
18+
private String password;
19+
20+
public SimpleUser(User user) {
21+
this.userId = user.getId();
22+
this.username = user.getUsername();
23+
this.password = user.getPassword();
24+
}
25+
26+
public long getUserId() {
27+
return userId;
28+
}
29+
30+
@Override
31+
public String getPassword() {
32+
return password;
33+
}
34+
35+
@Override
36+
public String getUsername() {
37+
return username;
38+
}
39+
40+
@Override
41+
public Collection<? extends GrantedAuthority> getAuthorities() {
42+
return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"));
43+
}
44+
45+
@Override
46+
public boolean isAccountNonExpired() {
47+
return true;
48+
}
49+
50+
@Override
51+
public boolean isAccountNonLocked() {
52+
return true;
53+
}
54+
55+
@Override
56+
public boolean isCredentialsNonExpired() {
57+
return true;
58+
}
59+
60+
@Override
61+
public boolean isEnabled() {
62+
return true;
63+
}
64+
65+
@Override
66+
public boolean equals(Object o) {
67+
if (this == o) return true;
68+
if (!(o instanceof SimpleUser)) return false;
69+
SimpleUser that = (SimpleUser) o;
70+
return Objects.equals(username, that.username);
71+
}
72+
73+
@Override
74+
public int hashCode() {
75+
return Objects.hash(username);
76+
}
77+
78+
@Override
79+
public String toString() {
80+
return "SimpleUser{" +
81+
"userId=" + userId +
82+
", username='" + username + '\'' +
83+
", password='" + password + '\'' +
84+
'}';
85+
}
86+
}

src/main/java/com/taskagile/domain/model/user/User.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public static User create(String username, String emailAddress, String password)
5252
return user;
5353
}
5454

55+
public void updateName(String firstName, String lastName) {
56+
this.firstName = firstName;
57+
this.lastName = lastName;
58+
}
59+
5560
public Long getId() {
5661
return id;
5762
}

src/main/java/com/taskagile/utils/JsonUtils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
import com.fasterxml.jackson.core.JsonProcessingException;
44
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.taskagile.web.apis.authenticate.AuthenticationFilter;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

9+
import java.io.IOException;
10+
import java.io.Writer;
11+
812
public final class JsonUtils {
913

1014
private static final Logger log = LoggerFactory.getLogger(JsonUtils.class);
@@ -21,4 +25,19 @@ public static String toJson(Object object) {
2125
return null;
2226
}
2327
}
28+
29+
public static <T> T toObject(String json, Class<T> clazz) {
30+
try {
31+
ObjectMapper objectMapper = new ObjectMapper();
32+
return objectMapper.readValue(json, clazz);
33+
} catch (IOException e) {
34+
log.error("Failed to convert string `" + json + "` class `" + clazz.getName() + "`", e);
35+
return null;
36+
}
37+
}
38+
39+
public static void write(Writer writer, Object value) throws IOException {
40+
new ObjectMapper().writeValue(writer, value);
41+
}
42+
2443
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.taskagile.web.apis.authenticate;
2+
3+
import com.taskagile.utils.JsonUtils;
4+
import org.apache.commons.io.IOUtils;
5+
import org.apache.commons.lang3.StringUtils;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
import org.springframework.security.authentication.InsufficientAuthenticationException;
9+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
10+
import org.springframework.security.core.Authentication;
11+
import org.springframework.security.core.AuthenticationException;
12+
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
13+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
14+
15+
import javax.servlet.http.HttpServletRequest;
16+
import javax.servlet.http.HttpServletResponse;
17+
import java.io.IOException;
18+
19+
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
20+
21+
private static final Logger log = LoggerFactory.getLogger(AuthenticationFilter.class);
22+
23+
public AuthenticationFilter() {
24+
super(new AntPathRequestMatcher("/api/authentications", "POST"));
25+
}
26+
27+
@Override
28+
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
29+
throws AuthenticationException, IOException {
30+
31+
log.debug("Processing login request");
32+
33+
String requestBody = IOUtils.toString(request.getReader());
34+
LoginRequest loginRequest = JsonUtils.toObject(requestBody, LoginRequest.class);
35+
if (loginRequest == null || loginRequest.isInvalid()) {
36+
throw new InsufficientAuthenticationException("Invalid authentication request");
37+
}
38+
39+
UsernamePasswordAuthenticationToken token =
40+
new UsernamePasswordAuthenticationToken(loginRequest.username, loginRequest.password);
41+
return this.getAuthenticationManager().authenticate(token);
42+
}
43+
44+
static class LoginRequest {
45+
private String username;
46+
private String password;
47+
48+
public boolean isInvalid() {
49+
return StringUtils.isBlank(username) || StringUtils.isBlank(password);
50+
}
51+
52+
public String getUsername() {
53+
return username;
54+
}
55+
56+
public void setUsername(String username) {
57+
this.username = username;
58+
}
59+
60+
public String getPassword() {
61+
return password;
62+
}
63+
64+
public void setPassword(String password) {
65+
this.password = password;
66+
}
67+
}
68+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.taskagile.web.apis.authenticate;
2+
3+
import com.taskagile.web.results.ApiResult;
4+
import com.taskagile.utils.JsonUtils;
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.security.authentication.BadCredentialsException;
7+
import org.springframework.security.authentication.InsufficientAuthenticationException;
8+
import org.springframework.security.core.AuthenticationException;
9+
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
10+
11+
import javax.servlet.http.HttpServletRequest;
12+
import javax.servlet.http.HttpServletResponse;
13+
import java.io.IOException;
14+
15+
public class SimpleAuthenticationFailureHandler implements AuthenticationFailureHandler {
16+
17+
@Override
18+
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
19+
AuthenticationException exception) throws IOException {
20+
response.setStatus(HttpStatus.BAD_REQUEST.value());
21+
ApiResult failure;
22+
if (exception instanceof BadCredentialsException) {
23+
failure = ApiResult.message("Invalid credentials");
24+
} else if (exception instanceof InsufficientAuthenticationException) {
25+
failure = ApiResult.message("Invalid authentication request");
26+
} else {
27+
failure = ApiResult.message("Authentication failure");
28+
}
29+
JsonUtils.write(response.getWriter(), failure);
30+
}
31+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy