JAVA-8360 Split or move spring-5-security module
This commit is contained in:
-50
@@ -1,50 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException {
|
||||
|
||||
if (!request.getMethod().equals("POST")) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: "
|
||||
+ request.getMethod());
|
||||
}
|
||||
|
||||
CustomAuthenticationToken authRequest = getAuthRequest(request);
|
||||
setDetails(request, authRequest);
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
|
||||
private CustomAuthenticationToken getAuthRequest(HttpServletRequest request) {
|
||||
String username = obtainUsername(request);
|
||||
String password = obtainPassword(request);
|
||||
String domain = obtainDomain(request);
|
||||
|
||||
if (username == null) {
|
||||
username = "";
|
||||
}
|
||||
if (password == null) {
|
||||
password = "";
|
||||
}
|
||||
if (domain == null) {
|
||||
domain = "";
|
||||
}
|
||||
|
||||
return new CustomAuthenticationToken(username, password, domain);
|
||||
}
|
||||
|
||||
private String obtainDomain(HttpServletRequest request) {
|
||||
return request.getParameter(SPRING_SECURITY_FORM_DOMAIN_KEY);
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class CustomAuthenticationToken extends UsernamePasswordAuthenticationToken {
|
||||
|
||||
private String domain;
|
||||
|
||||
public CustomAuthenticationToken(Object principal, Object credentials, String domain) {
|
||||
super(principal, credentials);
|
||||
this.domain = domain;
|
||||
super.setAuthenticated(false);
|
||||
}
|
||||
|
||||
public CustomAuthenticationToken(Object principal, Object credentials, String domain,
|
||||
Collection<? extends GrantedAuthority> authorities) {
|
||||
super(principal, credentials, authorities);
|
||||
this.domain = domain;
|
||||
super.setAuthenticated(true); // must use super, as we override
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return this.domain;
|
||||
}
|
||||
}
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
|
||||
/**
|
||||
* The plaintext password used to perform
|
||||
* PasswordEncoder#matches(CharSequence, String)} on when the user is
|
||||
* not found to avoid SEC-2056.
|
||||
*/
|
||||
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private CustomUserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* The password used to perform
|
||||
* {@link PasswordEncoder#matches(CharSequence, String)} on when the user is
|
||||
* not found to avoid SEC-2056. This is necessary, because some
|
||||
* {@link PasswordEncoder} implementations will short circuit if the password is not
|
||||
* in a valid format.
|
||||
*/
|
||||
private String userNotFoundEncodedPassword;
|
||||
|
||||
public CustomUserDetailsAuthenticationProvider(PasswordEncoder passwordEncoder, CustomUserDetailsService userDetailsService) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
|
||||
if (authentication.getCredentials() == null) {
|
||||
logger.debug("Authentication failed: no credentials provided");
|
||||
throw new BadCredentialsException(
|
||||
messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||
}
|
||||
|
||||
String presentedPassword = authentication.getCredentials()
|
||||
.toString();
|
||||
|
||||
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
|
||||
logger.debug("Authentication failed: password does not match stored value");
|
||||
throw new BadCredentialsException(
|
||||
messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAfterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
|
||||
this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
|
||||
throws AuthenticationException {
|
||||
CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;
|
||||
UserDetails loadedUser;
|
||||
|
||||
try {
|
||||
loadedUser = this.userDetailsService.loadUserByUsernameAndDomain(auth.getPrincipal()
|
||||
.toString(), auth.getDomain());
|
||||
} catch (UsernameNotFoundException notFound) {
|
||||
if (authentication.getCredentials() != null) {
|
||||
String presentedPassword = authentication.getCredentials()
|
||||
.toString();
|
||||
passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword);
|
||||
}
|
||||
throw notFound;
|
||||
} catch (Exception repositoryProblem) {
|
||||
throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
||||
}
|
||||
|
||||
if (loadedUser == null) {
|
||||
throw new InternalAuthenticationServiceException("UserDetailsService returned null, "
|
||||
+ "which is an interface contract violation");
|
||||
}
|
||||
return loadedUser;
|
||||
}
|
||||
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public interface CustomUserDetailsService {
|
||||
|
||||
UserDetails loadUserByUsernameAndDomain(String username, String domain) throws UsernameNotFoundException;
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service("userDetailsService")
|
||||
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
|
||||
|
||||
private UserRepository userRepository;
|
||||
|
||||
public CustomUserDetailsServiceImpl(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsernameAndDomain(String username, String domain) throws UsernameNotFoundException {
|
||||
if (StringUtils.isAnyBlank(username, domain)) {
|
||||
throw new UsernameNotFoundException("Username and domain must be provided");
|
||||
}
|
||||
User user = userRepository.findUser(username, domain);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(
|
||||
String.format("Username not found for domain, username=%s, domain=%s",
|
||||
username, domain));
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository("userRepository")
|
||||
public class CustomUserRepository implements UserRepository {
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public CustomUserRepository(PasswordEncoder passwordEncoder) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findUser(String username, String domain) {
|
||||
if (StringUtils.isAnyBlank(username, domain)) {
|
||||
return null;
|
||||
} else {
|
||||
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
|
||||
User user = new User(username, domain,
|
||||
passwordEncoder.encode("secret"), true,
|
||||
true, true, true, authorities);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ExtraLoginFieldsApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ExtraLoginFieldsApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class PasswordEncoderConfiguration {
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@PropertySource("classpath:/application-extrafields.properties")
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http
|
||||
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||
.authorizeRequests()
|
||||
.antMatchers("/css/**", "/index").permitAll()
|
||||
.antMatchers("/user/**").authenticated()
|
||||
.and()
|
||||
.formLogin().loginPage("/login")
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/logout");
|
||||
}
|
||||
|
||||
public CustomAuthenticationFilter authenticationFilter() throws Exception {
|
||||
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
|
||||
filter.setAuthenticationManager(authenticationManagerBean());
|
||||
filter.setAuthenticationFailureHandler(failureHandler());
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(authProvider());
|
||||
}
|
||||
|
||||
public AuthenticationProvider authProvider() {
|
||||
CustomUserDetailsAuthenticationProvider provider
|
||||
= new CustomUserDetailsAuthenticationProvider(passwordEncoder, userDetailsService);
|
||||
return provider;
|
||||
}
|
||||
|
||||
public SimpleUrlAuthenticationFailureHandler failureHandler() {
|
||||
return new SimpleUrlAuthenticationFailureHandler("/login?error=true");
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class User extends org.springframework.security.core.userdetails.User {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String domain;
|
||||
|
||||
public User(String username, String domain, String password, boolean enabled,
|
||||
boolean accountNonExpired, boolean credentialsNonExpired,
|
||||
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
public interface UserRepository {
|
||||
|
||||
public User findUser(String username, String domain);
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.baeldung.loginextrafieldscustom;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class WebController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String root() {
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
@RequestMapping("/index")
|
||||
public String index(Model model) {
|
||||
getDomain().ifPresent(d -> {
|
||||
model.addAttribute("domain", d);
|
||||
});
|
||||
return "index";
|
||||
}
|
||||
|
||||
@RequestMapping("/user/index")
|
||||
public String userIndex(Model model) {
|
||||
getDomain().ifPresent(d -> {
|
||||
model.addAttribute("domain", d);
|
||||
});
|
||||
return "user/index";
|
||||
}
|
||||
|
||||
@RequestMapping("/login")
|
||||
public String login() {
|
||||
return "login";
|
||||
}
|
||||
|
||||
private Optional<String> getDomain() {
|
||||
Authentication auth = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
String domain = null;
|
||||
if (auth != null && !auth.getClass().equals(AnonymousAuthenticationToken.class)) {
|
||||
User user = (User) auth.getPrincipal();
|
||||
domain = user.getDomain();
|
||||
}
|
||||
return Optional.ofNullable(domain);
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ExtraLoginFieldsApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ExtraLoginFieldsApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class PasswordEncoderConfiguration {
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@PropertySource("classpath:/application-extrafields.properties")
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http
|
||||
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||
.authorizeRequests()
|
||||
.antMatchers("/css/**", "/index").permitAll()
|
||||
.antMatchers("/user/**").authenticated()
|
||||
.and()
|
||||
.formLogin().loginPage("/login")
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/logout");
|
||||
}
|
||||
|
||||
public SimpleAuthenticationFilter authenticationFilter() throws Exception {
|
||||
SimpleAuthenticationFilter filter = new SimpleAuthenticationFilter();
|
||||
filter.setAuthenticationManager(authenticationManagerBean());
|
||||
filter.setAuthenticationFailureHandler(failureHandler());
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(authProvider());
|
||||
}
|
||||
|
||||
public AuthenticationProvider authProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
provider.setPasswordEncoder(passwordEncoder);
|
||||
return provider;
|
||||
}
|
||||
|
||||
public SimpleUrlAuthenticationFailureHandler failureHandler() {
|
||||
return new SimpleUrlAuthenticationFailureHandler("/login?error=true");
|
||||
}
|
||||
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
public class SimpleAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException {
|
||||
|
||||
if (!request.getMethod()
|
||||
.equals("POST")) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken authRequest = getAuthRequest(request);
|
||||
setDetails(request, authRequest);
|
||||
return this.getAuthenticationManager()
|
||||
.authenticate(authRequest);
|
||||
}
|
||||
|
||||
private UsernamePasswordAuthenticationToken getAuthRequest(HttpServletRequest request) {
|
||||
String username = obtainUsername(request);
|
||||
String password = obtainPassword(request);
|
||||
String domain = obtainDomain(request);
|
||||
|
||||
if (username == null) {
|
||||
username = "";
|
||||
}
|
||||
if (password == null) {
|
||||
password = "";
|
||||
}
|
||||
if (domain == null) {
|
||||
domain = "";
|
||||
}
|
||||
|
||||
String usernameDomain = String.format("%s%s%s", username.trim(),
|
||||
String.valueOf(Character.LINE_SEPARATOR), domain);
|
||||
return new UsernamePasswordAuthenticationToken(usernameDomain, password);
|
||||
}
|
||||
|
||||
private String obtainDomain(HttpServletRequest request) {
|
||||
return request.getParameter(SPRING_SECURITY_FORM_DOMAIN_KEY);
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service("userDetailsService")
|
||||
public class SimpleUserDetailsService implements UserDetailsService {
|
||||
|
||||
private UserRepository userRepository;
|
||||
|
||||
public SimpleUserDetailsService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
String[] usernameAndDomain = StringUtils.split(username, String.valueOf(Character.LINE_SEPARATOR));
|
||||
if (usernameAndDomain == null || usernameAndDomain.length != 2) {
|
||||
throw new UsernameNotFoundException("Username and domain must be provided");
|
||||
}
|
||||
User user = userRepository.findUser(usernameAndDomain[0], usernameAndDomain[1]);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(
|
||||
String.format("Username not found for domain, username=%s, domain=%s",
|
||||
usernameAndDomain[0], usernameAndDomain[1]));
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository("userRepository")
|
||||
public class SimpleUserRepository implements UserRepository {
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public SimpleUserRepository(PasswordEncoder passwordEncoder) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findUser(String username, String domain) {
|
||||
if (StringUtils.isAnyBlank(username, domain)) {
|
||||
return null;
|
||||
} else {
|
||||
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
|
||||
User user = new User(username, domain,
|
||||
passwordEncoder.encode("secret"), true,
|
||||
true, true, true, authorities);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class User extends org.springframework.security.core.userdetails.User {
|
||||
|
||||
private String domain;
|
||||
|
||||
public User(String username, String domain, String password, boolean enabled,
|
||||
boolean accountNonExpired, boolean credentialsNonExpired,
|
||||
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
public interface UserRepository {
|
||||
|
||||
public User findUser(String username, String domain);
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.baeldung.loginextrafieldssimple;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class WebController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String root() {
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
@RequestMapping("/index")
|
||||
public String index(Model model) {
|
||||
getDomain().ifPresent(d -> {
|
||||
model.addAttribute("domain", d);
|
||||
});
|
||||
return "index";
|
||||
}
|
||||
|
||||
@RequestMapping("/user/index")
|
||||
public String userIndex(Model model) {
|
||||
getDomain().ifPresent(d -> {
|
||||
model.addAttribute("domain", d);
|
||||
});
|
||||
return "user/index";
|
||||
}
|
||||
|
||||
@RequestMapping("/login")
|
||||
public String login() {
|
||||
return "login";
|
||||
}
|
||||
|
||||
private Optional<String> getDomain() {
|
||||
Authentication auth = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
String domain = null;
|
||||
if (auth != null && !auth.getClass().equals(AnonymousAuthenticationToken.class)) {
|
||||
User user = (User) auth.getPrincipal();
|
||||
domain = user.getDomain();
|
||||
}
|
||||
return Optional.ofNullable(domain);
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
spring.thymeleaf.prefix = classpath:/templatesextrafields/
|
||||
@@ -1,8 +0,0 @@
|
||||
p.error {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
div.logout {
|
||||
margin-right: 2em;;
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security" lang="en">
|
||||
<head>
|
||||
<title>Spring Security with Extra Fields</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
|
||||
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="logout float-right" th:fragment="logout" sec:authorize="isAuthenticated()">
|
||||
<p>Logged in: <span sec:authentication="name"></span> | <span th:text="${domain}">Some Domain</span>
|
||||
</p>
|
||||
<div>
|
||||
<form action="#" th:action="@{/logout}" method="post">
|
||||
<button class="btn btn-sm btn-primary btn-block" type="submit">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Hello Spring Security</h2>
|
||||
<p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
|
||||
<ul>
|
||||
<li>Go to the <a href="/user/index" th:href="@{/user/index}">secured pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<title>Login page</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
|
||||
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<form class="form-signin" th:action="@{/login}" method="post">
|
||||
<h2 class="form-signin-heading">Please sign in</h2>
|
||||
<p>Example: user / domain / password</p>
|
||||
<p th:if="${param.error}" class="error">Invalid user, password, or domain</p>
|
||||
<p>
|
||||
<label for="username" class="sr-only">Username</label>
|
||||
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="domain" class="sr-only">Domain</label>
|
||||
<input type="text" id="domain" name="domain" class="form-control" placeholder="Domain" required autofocus/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="sr-only">Password</label>
|
||||
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required autofocus/>
|
||||
</p>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button><br/>
|
||||
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<title>Secured Page</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
|
||||
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div th:replace="index::logout"></div>
|
||||
<h2>This is a secured page!</h2>
|
||||
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user