How to do it...

Instead of hardcoding the user details inside the security model, we will implement a service layer that will programmatically generate a username and password for the application:

  1. Let us create the UserService interface, as follows that will generate hardcoded data for the UserDetails:
public interface UserService { 
   
  public String getUserCredentials(String username); 
  public Set<String> getuserRoles(String username); 
} 
  1. Save this file in our org.secured.mvc.service since this is just an application-based native service.
  2. Then, implement the interface through UserServiceImpl as follows:
@Service("userService") 
public class UserServiceImpl implements UserService{ 
 
  @Override 
  public String getUserCredentials(String username) { 
    Map<String, String> credentials = new HashMap<>(); 
    credentials.put("sjctrags", "sjctrags"); 
    credentials.put("admin", "admin"); 
    credentials.put("hradmin", "hradmin"); 
    return credentials.get(username); 
  } 
 
  @Override 
  public Set<String> getuserRoles(String username) { 
    Map<String, Set<String>> roles = new HashMap<>(); 
    Set<String> userA = new HashSet<>(); 
    Set<String> userB = new HashSet<>(); 
    Set<String> userC = new HashSet<>(); 
    userA.add("ROLE_USER"); 
    userB.add("ROLE_ADMIN"); 
    userB.add("ROLE_USER"); 
    userC.add("ROLE_HR"); 
    userC.add("ROLE_ADMIN"); 
    roles.put("sjctrags", userA); 
    roles.put("admin", userB); 
    roles.put("hradmin", userC); 
    return roles.get(username); 
  } 
} 
  1. Now, create an implementation of UserDetailsService, which retrieves the user information through its username and provides this corresponding information to SecurityContext:
@Service("authUserService") 
public class AuthUserService implements UserDetailsService { 
   
  @Autowired 
  private UserService userService; 
 
  @Override 
  public UserDetails loadUserByUsername(String username)  
    throws UsernameNotFoundException { 
    String password =   
       userService.getUserCredentials(username); 
    UserDetails user = new User(username, password, true,  
       true,  
    true, true, getAuthorities(username)); 
    return user; 
  } 
   
  private Set<GrantedAuthority> getAuthorities(String username){ 
    Set<GrantedAuthority> authorities =  
       new HashSet<GrantedAuthority>(); 
    for(String role : userService.getuserRoles(username)) { 
         GrantedAuthority grantedAuthority =  
           new SimpleGrantedAuthority(role); 
         authorities.add(grantedAuthority); 
      } 
      return authorities; 
    } 
} 
  1. Place this class inside the org.packt.secured.mvc.core.service package. We will be injecting this class inside our Spring Security container.
  2. Design now the AppSecurityModelD that will utilize UserDetails and UserDetailsService for storing and retrieving user identification:
@Configuration 
@EnableWebSecurity 
public class AppSecurityModelD extends  
    WebSecurityConfigurerAdapter { 
   
  // refer to sources 
@Autowired 
@Qualifier("authUserService") 
private UserDetailsService userDetailsService; 
   
  @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.userDetailsService(userDetailsService); 
    auth.eraseCredentials(false); 
    } 
     
  @Override 
  protected void configure(HttpSecurity http) throws Exception { 
      http 
        .authorizeRequests() 
        .antMatchers("/login**", "/after**").permitAll() 
        .anyRequest().authenticated() 
        .and() 
        .formLogin() 
        .loginPage("/login.html") 
        .defaultSuccessUrl("/deptform.html") 
        .failureUrl("/login.html?error=true") 
        .successHandler(customSuccessHandler) 
        .and() 
        .logout().logoutUrl("/logout.html") 
        .logoutSuccessHandler(customLogoutHandler); 
    
       http.csrf().disable(); 
 } 
    
  @Override 
  public void configure(WebSecurity web) throws Exception { 
        // refer to sources    
  } 
} 
  1. For evidence that UserDetails have been injected into SecurityContext, utilize the CustomSuccessHandler and CustomLogoutHandler of the previous recipe. Modify a little bit the CustomLogoutHandler to extract the user credentials and roles using the java.security.Principal object:
@Component 
public class CustomLogoutHandler extends  
    SimpleUrlLogoutSuccessHandler { 
   
  private RedirectStrategy redirectStrategy =  
    new DefaultRedirectStrategy(); 
   
  @Override 
  public void onLogoutSuccess(HttpServletRequest request,  
    HttpServletResponse response, Authentication  
     authentication) throws IOException, ServletException { 
     
     String targetUrl = targetUrl(authentication); 
         // refer to sources 
     redirectStrategy.sendRedirect(request, response,  
        targetUrl); 
  } 
   
  protected String targetUrl(Authentication authentication) { 
    UserDetails p =     
      (UserDetails )authentication.getPrincipal(); 
    String username = p.getUsername(); 
    String password = p.getPassword(); 
    String url = ""; 
    Collection<? extends GrantedAuthority> authorities =  
        p.getAuthorities(); 
    List<String> roles = new ArrayList<String>(); 
    for (GrantedAuthority a : authorities) { 
            roles.add(a.getAuthority()); 
    } 
        if (isUser(roles)) { 
          url = "/after_logout.html?message=" + " Thank  
          your, " + username + " with password " + password  
            +" and role(s):" + roles; 
        }  
      // refer to sources 
        return url; 
    } 
    // refer to sources 
}
  1. Be sure to update SpringContextConfig by importing the new AppSecurityModelD and including the org.packt.secured.mvc.core.service in its @ComponentScan.
  2. Save all files. clean, build, and deploy the Maven project.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.21.152