Spring Security

Spring SecuritySpring SecuritySpring Security provides comprehensive security services for Java EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading Java EE solution for enterprise software development.

As you probably know two major areas of application security are “authentication” and “authorization” (or “access-control”). These are the two main areas that Spring Security targets. “Authentication” is the process of establishing a principal is who they claim to be (a “principal” generally means a user, device or some other system which can perform an action in your application).”Authorization” refers to the process of deciding whether a principal is allowed to perform an action within your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. These concepts are common, and not at all specific to Spring Security.

At an authentication level, Spring Security supports a wide range of authentication models. Most of these authentication models are either provided by third parties, or are developed by relevant standards bodies such as the Internet Engineering Task Force. In addition, Spring Security provides its own set of authentication features.

Java Configuration
General support for Java Configuration was added to Spring Framework in Spring 3.1. Since Spring Security 3.2 there has been Spring Security Java Configuration support which enables users to easily configure Spring Security without the use of any XML.

Technologies used :

  1. Spring 3.2.2.RELEASE
  2. Spring Security 3.2.2.RELEASE
  3. Hibernate 4.2.1.Final
  4. MySQL Server 5.1.25
  5. Tomcat 7 (Servlet 3.x container)

Note: Add all these dependencies in pom.xml

Web/Spring Security Java Configuration
The first step is to create our Spring Security Java Configuration. The configuration creates a Servlet Filter known as the springSecurityFilterChain which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the login form, etc) within your application. You can find the most basic example of a Spring Security Java Configuration below:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.web.authentication.AuthenticationSuccessHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  @Qualifier(“customUserDetailsService”)
  UserDetailsService userDetailsService;
  @Autowired
  CustomSuccessHandler customSuccessHandler;
  @Autowired
  AuthenticationSuccessHandler authenticationSuccessHandler;
  @Autowired
  public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService);
  }
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http
              .authorizeRequests()
              .antMatchers(“/index**”, “/home**”, “/login**”, “/resources**”, “/pages**”).permitAll()
              .antMatchers(“/admin/**”).hasRole(“ADMIN”)
              .antMatchers(“/manager/**”).hasAnyRole(“ADMIN”,“MANAGER”)
              .anyRequest().authenticated()
              .and()
              .formLogin()
              .loginPage(“/login”)
              .failureUrl(“/login?error=true”)
              .defaultSuccessUrl(“/indexHome”)
              .usernameParameter(“email”).passwordParameter(“password”).permitAll()
              .successHandler(customSuccessHandler)
              .and()
              .logout()
              .logoutSuccessUrl(“/login?logout”)
              .invalidateHttpSession(true).deleteCookies(“JSESSIONID”).permitAll()
              .and()
              .exceptionHandling().accessDeniedPage(“/403”)
              .and().csrf().disable();
  }
}

AbstractSecurityWebApplicationInitializer with Spring MVC
If you were using Spring elsewhere in our application we probably already had a WebApplicationInitializer that is loading our Spring Configuration. If we use the previous configuration we would get an error. Instead, we should register Spring Security with the existing ApplicationContext. For example, if we were using Spring MVC our SecurityWebApplicationInitializer would look something like the following:

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
This would simply only register the springSecurityFilterChain Filter for every URL in your application.

Authorize Requests
Our examples have only required users to be authenticated and have done so for every URL in our application. We can specify custom requirements for our URLs by adding multiple children to our http.authorizeRequests() method. For example:
@Override
protected void configure(HttpSecurity http) throws Exception {
  http
          .authorizeRequests()
          .antMatchers(“/index**”, “/home**”, “/login**”, “/resources**”, “/pages**”).permitAll()
          .antMatchers(“/admin/**”).hasRole(“ADMIN”)
          .antMatchers(“/manager/**”).hasAnyRole(“ADMIN”,“MANAGER”)
          .anyRequest().authenticated()                       
          .and()

Authentication
Create a new custom class that will implement AuthenticationSuccessHandler. Then add your logic on how you want to handle whenever the user successfully logs in. For this example, if ever the user successfully logs in, we will add his username and his roles to its session and redirect him to the home page.

@Component
public class CustomSuccessHandler implements AuthenticationSuccessHandler {
  private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
  @Autowired
  PermissionsRepository permissionsRepository;
  @Autowired
  PageRepository pageRepository;
  
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
      handle(request, response, authentication);
      HttpSession session = request.getSession(false);
      if (session != null) {
          session.setMaxInactiveInterval(10 * 60);
          org.springframework.security.core.userdetails.User authUser = (org.springframework.security.core.userdetails.User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
          session.setAttribute(“userName”, authUser.getUsername());
          session.setAttribute(“authorities”, authentication.getAuthorities());
      }
      clearAuthenticationAttributes(request);
  }
  protected void handle(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException {
      final String targetUrl = determineTargetUrl(authentication);
      if (response.isCommitted()) {
          System.out.println(“User resourceURL’s are ” + targetUrl);
          return;
      }
      redirectStrategy.sendRedirect(request, response, targetUrl);
  }
  protected String determineTargetUrl(Authentication authentication) {
      Set roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
      List availablePermissions = permissionsRepository.findAll();
      List permissionsList = new ArrayList<>();
      List PagesURL = pageRepository.findAll();
      List availablePageUrlList = new ArrayList<>();
      for (Permissions avlblPermissions : availablePermissions) {
          permissionsList.add(avlblPermissions.getPermission());
      }
      System.out.println(“List of Permissions’s are ” + permissionsList + “”);
      for (Page PageURLs : PagesURL) {
          availablePageUrlList.add(PageURLs.getPageUrl());
      }
      System.out.println(“List of available Page’s are ” + availablePageUrlList + “”);

      if (roles.contains(“ROLE_ADMIN”) && permissionsList.contains(“DELETE_PRIVILEGE”) && availablePageUrlList.contains(http://localhost:8080/admin&#8221;)) {
          return “/admin”;
      } else if (roles.contains(“ROLE_MANAGER”) && permissionsList.contains(“WRITE_PRIVILEGE”) && availablePageUrlList.contains(http://localhost:8080/manager&#8221;)) {
          return “/manager”;

      } else if (roles.contains(“ROLE_USER”) && permissionsList.contains(“READ_PRIVILEGE”) && availablePageUrlList.contains(http://localhost:8080/user&#8221;)) {
          return “/user”;
      } else {
          return “/403”;
      }
  }
  protected void clearAuthenticationAttributes(HttpServletRequest request) {
      HttpSession session = request.getSession(false);
      if (session == null) {
          return;
      }
      session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
  }
  public RedirectStrategy getRedirectStrategy() {
      return redirectStrategy;
  }
  public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
      this.redirectStrategy = redirectStrategy;
  }
}
Note: In this example, we are getting and checking all the Users, Roles, Privileges and Page URL’s Dynamically from Database.

Controllers
I have Implemented with User specific controllers as in below for ‘admin’ likewise to Manager/DBA/User.

@Controller
@RequestMapping(value = “/admin”)
public class AdminController extends SecurityLoginController {
  private static final String viewPrefix = “security/Pages/admin”;
  private static final String accessDeniedViewPrefix = “security/AccessDenied/”;
  @Autowired
  private UsersRepository userRepository;
  @Autowired
  private UsersService userService;
  @RequestMapping(value = “”, method = RequestMethod.GET)
  public String adminPage(ModelMap model) {
      model.addAttribute(“user”, getPrincipal());
      return viewPrefix;

Case 1. Open browser with the url  http://localhost:8080/login  and enter user “ram@gmail.com” and password “admin123” and click on login

normalusertohomepage

You will see below Home screen as the user ram@gmail.com is only a normal user

Case 2. Try access a password protected unauthorized page;  http://localhost:8080/admin, an access denied page is displayed as the user is a normal user and is not authorized to access admin page.

normalusertoadminpage

Similarly, if you try to access; http://localhost:8080/manager  page you will be displayed with below.

normalusertomanagerpage

Case 3. If you try to access with wrong credentials you will be displayed with below screen

invalidcredentials

Advertisements