Spring Security doesn't differentiate roles - java

I am doing basic authentication using Spring Security using DaoAuthenticationProvider. I want to preauthorize my requests, so I am using the #PreAuthorize annotation. The problem is that it appears that Spring Security doesn't differentiate between multiple roles and authorities. For example, if I access /users, I am being prompted to the login screen, but no matter what user I login with, I always get the list of all users displayed. This is not what I want to achieve I want to restrict access to users list to the role admin.
Here is my SecurityConfig:
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
#RequiredArgsConstructor(onConstructor = #__({#Autowired}))
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Resource(name = "userRestClient")
UserService userService;
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
#Qualifier("authenticationProvider")
public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Autowired
public void configureAuthManager(AuthenticationManagerBuilder authenticationManagerBuilder) {
authenticationManagerBuilder.authenticationProvider(authenticationProvider);
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
// authProvider.setPasswordEncoder(encoder());
return authProvider;
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11);
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/", "/users", "/user").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout().permitAll();
httpSecurity
.csrf().disable();
httpSecurity
.headers()
.frameOptions().disable();
}
#Bean
protected UserDetailsService userDetailsService() {
return super.userDetailsService();
}
}
Here is my Controller:
#Controller
#Component
public class UserWebController {
private final UserRestClient userService = new UserRestClient();
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/users", method = RequestMethod.GET)
#Produces(MediaType.APPLICATION_JSON)
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.findAllUsers().stream().map(UserMapper.INSTANCE::from).collect(Collectors.toList());
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
}
My implementation of the UserDetails interface:
public class MyUser implements UserDetails {
private User user;
public MyUser(User user) {
this.user = user;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> roles = new HashSet<>();
roles.add(new Authority(user.getRole()));
return roles;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
User entity:
#Table(name = "users")
#AllArgsConstructor
#Data
#NoArgsConstructor
#javax.persistence.Entity
public class User extends Entity implements Serializable {
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "role")
private String role;
}

You have to enable #PreAuthorize, see EnableGlobalMethodSecurity#prePostEnabled:
Determines if Spring Security's pre post annotations should be enabled. Default is false.
Your modified and simplified configuration:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#RequiredArgsConstructor(onConstructor = #__({#Autowired}))
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Resource(name = "userRestClient")
UserService userService;
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
#Qualifier("authenticationProvider")
public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Autowired
public void configureAuthManager(AuthenticationManagerBuilder authenticationManagerBuilder) {
authenticationManagerBuilder.authenticationProvider(authenticationProvider);
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
return authProvider;
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder(11);
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/", "/users", "/user").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.csrf()
.disable()
.and()
.headers()
.frameOptions().disable();
}
#Bean
protected UserDetailsService userDetailsService() {
return super.userDetailsService();
}
}

Related

Unauthorized Error 401 to Existing Endpoint, No Error thrown in Server Log

I added Username and password field to an existing Customer entity. I have added a Custom JWT filter and authentication provider with a WebSecurityConfig annotated #Order(2). But when I send a post request with the Username and password payload , I get an Unauthorized Error 401 response But no error message in Server Log I have checked the WebConfig file appropriately .What am I not getting right ? I've been on this all day and I seem to be frustrated already.
This is UserDetails class
public class MyCustomerDetails implements UserDetails{
/**
*
*/
private static final long serialVersionUID = -5087929420394311276L;
private Long id;
private String username;
private String password;
public MyCustomerDetails() {
}
public MyCustomerDetails(Long id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public static MyCustomerDetails build(Customer customer) {
return new MyCustomerDetails(customer.getId(),
customer.getUserName(), customer.getPassword());
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
#Override
public String getPassword() {
// TODO Auto-generated method stub
return password;
}
#Override
public String getUsername() {
// TODO Auto-generated method stub
return username;
}
............
This is the Controller class
#CrossOrigin(origins = {"http://localhost:3000"})
#RestController
public class CustomerController {
#Autowired
CustomerAccountService customerRepo;
#Autowired
private CustomerJwtTokenUtil customerJwtTokenUtil;
#Autowired
private AuthenticationManager authenticationManager;
#PostMapping(value="/validateCustomer")
public ResponseEntity <?> createAuthenticationToken( #RequestBody MyCustomerDetails
authenticationRequest) throws Exception
{
authenticate(authenticationRequest.getUsername(),
authenticationRequest.getPassword());
// Long userId = authenticationRequest.getId();
final MyCustomerDetails userDetails =
(MyCustomerDetails) customerRepo.loadUserByUsername(authenticationRequest.getUsername());
final String token =
customerJwtTokenUtil.generateToken(userDetails);
return new ResponseEntity<>(new JwtResponse(token), HttpStatus.OK) ;
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
This is the WebSecurityconfig class
#Configuration
#Order(2)
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomerSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomerJwtAuthenticationEntryPoint customerJwtAuthenticationEntryPoint;
#Autowired
private UserDetailsService myCustomerDetailsService;
#Autowired
private CustomerJwtRequestFilter customerJwtRequestFilter;
#Bean
public CustomerAccountService myCustomerAccountService() {
return new CustomerAccountService();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/*
* #Bean public UserDetailsService myCustomerDetailsService() { return
* myCustomerDetailsService(); }
*/
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder,
UserDetailsService userDetailsService){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
return daoAuthenticationProvider;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
protected void configure(AuthenticationManagerBuilder auth ) throws Exception {
auth.userDetailsService(myCustomerDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/***").permitAll()
// .antMatchers("/customer/**").hasAuthority("CUSTOMER")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(customerJwtAuthenticationEntryPoint)
.and()
.formLogin().permitAll()
// .loginPage("/login")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login")
.and()
.sessionManagement()
.maximumSessions(1)
.and()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(customerJwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
The Service class
#Primary
public class CustomerAccountService implements UserDetailsService {
#Autowired
private CustomerAccountRepo custRepo;
#Qualifier("passwordEncoder")
#Autowired
private PasswordEncoder bCryptPasswordEncoder;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Customer customer = custRepo.findByUserName(username);
if(customer == null) {
throw new UsernameNotFoundException("Customer not found");
}
return MyCustomerDetails.build(customer);
}
This is the Base class
#Configuration
#EnableWebMvc
//#ComponentScan(basePackages = "com.bethsaida.org.security")
#EnableJpaRepositories
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class BethsaidaApplication {
public static void main(String[] args)
{SpringApplication.run(BethsaidaApplication.class, args);}
public class WebConfig implements WebMvcConfigurer
{
private static final long MAX_AGE_SECS = 3600;
#Override
public void addCorsMappings(CorsRegistry registry)
{ registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
.maxAge(MAX_AGE_SECS);}
}
}
You can use this
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "PUT", "DELETE")
.allowedHeaders("header1", "header2")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
inside your CustomerSecurityConfiguration class directly.
Because WebMvcConfigurer is implemented by WebMvcConfigurerAdapter so you can define this method inside your CustomerSecurityConfiguration class.
For more information, you can see here

Spring Security: issues 403 after authorization with single granted

Used Spring Boot 2 + Spring Security Starter.
Authorizes users, but for some reason gives an error 403.
I tried to configure in different ways, but it does not work.
After successful authorization (the loadUserByUsername method works fine) it shows 403 on all pages with the / admin prefix, and before authorization, switching to any page with this prefix leads to a redirect to / login
#Controller
public class AdminController {
#RequestMapping(value = "/admin", method = {GET, POST})
public String adminMainPage() {
return "redirect:/admin/article";
}
}
#Controller
#RequestMapping("/admin/article")
public class ArticleController {
#RequestMapping(value = "", method = {GET, POST})
public ModelAndView indexAdminPage(...){
...
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements UserDetailsService {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.userDetailsService(this)
.authorizeRequests()
.antMatchers("/", "/login",
"/login*", "/assets/**", "/lib/**", "/page.scripts/*").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("login")
.passwordParameter("password")
.successForwardUrl("/admin")
.permitAll()
.and()
.logout()
.deleteCookies("JSESSIONID")
.permitAll();
}
private Collection<? extends GrantedAuthority> adminGrantedAuthoritySet = new HashSet<>() {{
add(new SimpleGrantedAuthority("ADMIN"));
}};
private final UserRepository userRepository;
public WebSecurityConfig(UserRepository userRepository ) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
Optional<UserEntity> optionalUser = userRepository.findByLogin(login);
if (optionalUser.isEmpty()) {
throw new UsernameNotFoundException("User by login '" + login + "' not found");
} else {
UserEntity userEntity = optionalUser.get();
return new User(login, userEntity.getPassword(), adminGrantedAuthoritySet);
}
}
}
In Spring Security there is a distinction between a role and an authority.
A role is an authority that is prefixed with "ROLE_". In this example the authority "ROLE_ADMIN" is the same as the role "ADMIN".
You are setting your admin authorities to be a list of new SimpleGrantedAuthority("ADMIN"), but you are restricting access to .hasAnyRole("ADMIN").
You need to change one of those configurations.
If you use .hasAnyRole("ADMIN"), then you should change the admin authorities list to use new SimpleGrantedAuthority("ROLE_ADMIN").
Otherwise, if you want your list to be new SimpleGrantedAuthority("ADMIN"), then you should use .hasAnyAuthority("ADMIN").
First, I will advice that you separate UserDetailsService from the WebSecurityConfig.
Have a separate class for UserDetailsService like
#Service("customCustomerDetailsService")
public class CustomCustomerDetailsService implements UserDetailsService {
#Autowired
private CustomerRepository customers;
#Override
public UserDetails loadUserByUsername(String email) {
return this.customers.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("Username: " + email + " not found"));
}
}
Then your UserEntity should implement UserDetails class where you set the authorities.See the answer //userdetails
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(SimpleGrantedAuthority::new).collect(toList());
}
#Override
public String getUsername() {
return this.getEmail();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Transient
private List<String> roles = Arrays.asList("ROLE_USER");
public List<String> getRoles() {
return roles;
}
Then you need DAOauthentication manager which makes use of the UserDetailsService like this:
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
#Bean
#Override
public UserDetailsService userDetailsService() {
return new CustomCustomerDetailsService();
}
I don't know think putting everything in the WebSecurityConfig is good practice and it will be complicated and prone to errors!

How to add PasswordEncoder into JdbcUserDetailsManager in Spring Security?

I'm learning about Spring Security and I want to add the BCryptPasswordEncoder at the JdbcUserDetailsManager.
This is the code:
#Configuration
#EnableWebSecurity
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Autowired
public UserDetailsManager userDetailsManager(DataSource securityDataSource) {
JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
jdbcUserDetailsManager.setDataSource(securityDataSource);
return jdbcUserDetailsManager;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").hasRole("EMPLOYEE")
.antMatchers("/leaders/**").hasRole("MANAGER")
.antMatchers("/systems/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authenticateTheUser")
.permitAll()
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
}
I need the UserDetailsManager bean to inject in other class. Thank you!
You should use this class to create the UserDetails Bean
#Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);
#Autowired
private com.fortsolution.schedmate.data.services.UserService userService;
#Transactional(readOnly=true)
public UserDetails loadUserByUsername(String ssoId)
throws UsernameNotFoundException {
System.out.println("fine here murtaza");
int id = Integer.parseInt(ssoId);
User user = userService.findById(id);
logger.info("User : {}", user);
if(user==null){
logger.info("User not found");
throw new UsernameNotFoundException("Username not found");
}
return new org.springframework.security.core.userdetails.User(""+user.getId(), user.getPassword(),
true, true, true, true, getGrantedAuthorities(user));
}
private List<GrantedAuthority> getGrantedAuthorities(User user){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(UserProfile userProfile : user.getUserProfiles()){
logger.info("UserProfile : {}", userProfile);
authorities.add(new SimpleGrantedAuthority("ROLE_"+userProfile.getType()));
}
return authorities;
}
}
after creating this class you will add these two method in your
#Autowired
#Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
#Override
#Autowired // <-- This is crucial otherwise Spring Boot creates its own
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
and
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}

Spring security authentication failing with BCryptPasswordEncoder

I'm new to spring and I'm trying to implement spring security in a project. I was able to create user with hash password using Bcrypt, but whenever I tried to login using the same password it fails. I've also tried checking other SO answers (like Spring Security BCryptPasswordEncoder Inserted But Not Match) non solved the issues faced.
Below is what have tried so far
WebSecurityConfigurerAdapter Class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsServiceImpl userDetailsService;
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
http.csrf().disable();
http.authorizeRequests().antMatchers("/login", "/app-assets/**", "/assets/**").permitAll();
http.authorizeRequests().antMatchers("/add-user", "/users-list").hasRole("ADMIN");
http.authorizeRequests().antMatchers("/", "/index", "/add-content", "/mange-content").hasAnyRole("ADMIN", "USER");
http
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/index")
.failureUrl("/login?error=true")
.usernameParameter("username")
.passwordParameter("password")
//.failureUrl("/login-error.html")
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/login?logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll();
}
#Bean
public DaoAuthenticationProvider authProvider() {
System.out.println("GOT CALLED HERE.....");
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
//auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
auth.authenticationProvider(authProvider());
}
}
UserDetailsService
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserDAO userDAO;
#Autowired
private RoleDAO roleDAO;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDAO.findUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User "+username+"not fount");
}
List<String> roleNames = roleDAO.getRoleNames(user.getAdminId());
System.out.println("USERNAME: "+user.getAdminId() + " "+user.getPassword());
List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();
if (roleNames != null) {
for (String role : roleNames) {
GrantedAuthority authority = new SimpleGrantedAuthority(role);
grantList.add(authority);
}
}
UserDetails userDetails = (UserDetails) new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantList);
return userDetails;
}
}
TEST
#RunWith(SpringRunner.class)
#SpringBootTest
public class ApplicationTests {
#Autowired
private UserDAO userDAO;
#Autowired
private BCryptPasswordEncoder encoder;
#Test
public void contextLoads() {
String password = "eureka";
String encrytedPassword = encoder.encode(password);
User user = userDAO.findUserByEmail("xxx#gmail.com");
System.out.println(encrytedPassword);
System.out.println("Matched: " + encoder.matches("eureka", encrytedPassword));//This line returns true
assertEquals(encrytedPassword, user.getPassword());
}
}
I also tried overriding matches() but to no avail
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder() {
#Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
// This throws an error
return matches(rawPassword, encodedPassword);
}
};
}
Note: Hashed password and raw password was gotten from matches() method. So there's no issues retrieving hashpassword from database.

Spring Security ldapAuthentication always successful

Implementing a ldapAuthentication into my Spring Security configuration makes the process ignoring the boolean field : "enabled" on Users (org.springframework.security.core.userdetails) so it's allowing disabled Users to connect..
The Security Config works well and it disallow disabled Users to connect with a simple authentication using userDetailsService but it fails with ldapAuthentication.
Here is SecurityConfig class :
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = {"com.mykeys.test"})
public class SecurityConfig {
#Resource
Environment environment;
#Resource
BaseLdapPathContextSource contextSource;
private static final String PROPERTY_NAME_SECURITY_KEY = "security.key";
#Resource(name="userDetailsService")
private UserDetailsService userDetailsService;
#Resource
public void configureAuthentification(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(userDetailsService);
auth.ldapAuthentication()
.userSearchFilter("uid={0}")
.ldapAuthoritiesPopulator(new UserDetailsServiceLdapAuthoritiesPopulator(userDetailsService))
.userSearchBase(environment.getProperty(LdapConfig.PROPERTY_LDAP_USER_SEARCH_BASE, LdapConfig.DEFAULT_LDAP_USER_SEARCH_BASE) )
.contextSource(contextSource);
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint())
.and()
.headers()
.addHeaderWriter(new StaticHeadersWriter("X-Frame-Options", "SAMEORIGIN"))
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Resource
Environment environment;
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/js/**", "/css/**", "/fonts/**", "/less/**", "/favicon.ico", "/holder.js/**", "/img/**", "/partial/**");
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.permitAll()
.defaultSuccessUrl("/")
.failureUrl("/login?error")
.and()
.logout()
.permitAll()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?error")
.and()
.and()
.rememberMe()
.key(environment.getProperty(PROPERTY_NAME_SECURITY_KEY, UUID.randomUUID().toString()))
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
}
Here is UserDetailsServiceImpl class (this bean is auto injected into SecurityConfig class):
#Service("userDetailsService")
#Transactional(readOnly = true)
public class UserDetailsServiceImpl implements UserDetailsService{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Resource MessageSource messageSource;
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
List<GrantedAuthority> list = getAllAuthor();
org.springframework.security.core.userdetails.User user = new org.springframework.security.core.userdetails.User(
username,
username,
false,
false,
false,
false,
list
);
return user;
} catch (Exception e) {
logger.warn("Authentification refusée pour l'utilisateur au login {}", username, e);
throw new UsernameNotFoundException(e.getMessage());
}
}
public static List<GrantedAuthority> getAllAuthor(){
Collection<String> roles = new ArrayList<>();
roles.add("ROLE1");
roles.add("ROLE2");
ArrayList<GrantedAuthority> authorities=new ArrayList<GrantedAuthority>();
if (roles != null) {
for (String roleName : roles) {
authorities.add(new SimpleGrantedAuthority(roleName));
}
}
return authorities;
}
}
And here is the LdapConfig class :
#Configuration
#EnableLdapRepositories
public class LdapConfig {
public static final String PROPERTY_LDAP_URL = "ldap.url";
public static final String DEFAULT_PROPERTY_LDAP_URL = "ldap://localhost:33899";
public static final String PROPERTY_LDAP_LDIF_FILE = "ldap.ldif";
public static final String DEFAULT_LDAP_LDIF_FILE = "classpath:data/ldif/corp.mykeys.com.ldif";
public static final String PROPERTY_LDAP_LOGIN_DN = "ldap.login.dn";
public static final String DEFAULT_PROPERTY_LDAP_LOGIN_DN = "LOGIN";
public static final String PROPERTY_LDAP_PASSWORD = "ldap.password";
public static final String DEFAULT_PROPERTY_LDAP_PASSWORD = "pass";
public static final String PROPERTY_LDAP_SEARCH_BASE = "ldap.searchbase";
public static final String DEFAULT_LDAP_SEARCH_BASE = "dc=corp,dc=mykeys,dc=com";
public static final String PROPERTY_LDAP_USER_SEARCH_BASE = "ldap.usersearchbase";
public static final String DEFAULT_LDAP_USER_SEARCH_BASE = "OU=FR,OU=Employees";
#Resource
Environment environment;
#Bean
BaseLdapPathContextSource contextSource() throws Exception {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(environment.getProperty(PROPERTY_LDAP_URL, DEFAULT_PROPERTY_LDAP_URL));
contextSource.setBase(environment.getProperty(PROPERTY_LDAP_SEARCH_BASE, DEFAULT_LDAP_SEARCH_BASE));
contextSource.setAnonymousReadOnly(true);
contextSource.setUserDn(environment.getProperty(PROPERTY_LDAP_LOGIN_DN, DEFAULT_PROPERTY_LDAP_LOGIN_DN));
contextSource.setPassword(environment.getProperty(PROPERTY_LDAP_PASSWORD, DEFAULT_PROPERTY_LDAP_PASSWORD));
if (environment.getProperty(PROPERTY_LDAP_URL, DEFAULT_PROPERTY_LDAP_URL).contains("ldap://localhost")) {
ldapServer();
}
return contextSource;
}
#Bean
LdapTemplate ldapTemplate() throws Exception { return new LdapTemplate(contextSource());
}
#Bean
#Lazy
public ApacheDSContainer ldapServer() throws Exception {
ApacheDSContainer apacheDSContainer= new ApacheDSContainer(environment.getProperty(PROPERTY_LDAP_SEARCH_BASE, DEFAULT_LDAP_SEARCH_BASE), environment.getProperty(PROPERTY_LDAP_LDIF_FILE, DEFAULT_LDAP_LDIF_FILE));
apacheDSContainer.setPort(Integer.valueOf(DEFAULT_PROPERTY_LDAP_URL.substring(DEFAULT_PROPERTY_LDAP_URL.lastIndexOf(":")+1)));
return apacheDSContainer;
}
#Bean
public String userSearchBase() {
return environment.getProperty(PROPERTY_LDAP_USER_SEARCH_BASE, DEFAULT_LDAP_USER_SEARCH_BASE);
}
}
And implementing a custom userDetailsContextMapper doesn't work too..

Categories