Friday, January 13, 2012

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 3)

Review

In the previous section, we have implemented the Java classes and organized them accordingly: domain, repository, service, and controller. In this section, we will create the necessary configuration files, which are mainly XML files, and discuss them thoroughly.


Configuration

There are two important configuration files required to secure our application with Spring Security:
  • spring-security.xml (arbitrary name)
  • web.xml

spring-security.xml

This contains the core Spring Security configuration.


Let's examine further the contents of this file:

the http tag

This means the path /resources should be ignored by Spring Security; therefore it will not be secured. Why do you want to do this? Mainly because these are static images, CSS, and JavaScript files that don't need to be secured.

the second http tag

This contains the core security rules of our application. In previous versions of Spring Security, you're only allowed to have one http element.
  • auto-config is a shorthand for the following (see more):

  • use-expressions allows us to use SPEL (Spring EL expressions) support (see more)

intercept urls

Here we declare URL patterns to be protected. Notice the use of SPEL hasRole and permitAll (see more)

form login

This declares our login settings:
  • login-page: the URL path of our login page
  • authentication-failure-url: the URL where a user will be redirected after a failed login
  • default-target-url: the URL where a user will be redirected after a successful login

denied handler

This declares the URL where a user will be redirected after a denied access.

authentication manager

This is similar with the login element.
  • logout-success-url: the URL where a user will be redirected after a successful logout
  • logout-url: the URL path of our logout page


  • authentication-manager: registers an AuthenticationManager that provides authentication services (see more)
  • authentication-provider: this is a shorthand for configuring a DaoAuthenticationProvider which loads user information from a UserDetailsService (see more)
  • user-service-ref: this allows us to declare a custom UserDetailsService
  • password-encoder: this allows us to declare various password encoders such as md5 and sha (see more)

web.xml

Besides the usual servlet declaration, the web.xml is where you declare the Spring Security filter and name of configuration file to read from.

To enable Spring Security, follow these guidelines:
  • Add a DelegatingFilterProxy
  • Add a springSecurityFilterChain mapping
  • Add a contextConfigLocation You must declare your applicationContext.xml and spring-security.xml here

Here's our complete web.xml file:


Datasource

Since we're using JPA and Spring Data JPA to simplify data access, we must also declare the corresponding configuration files. Please read the inline comments for more info.

spring-data.xml
This contains all datasource-related configuration.


Next

In the next section, we will turn our attention towards the view layer which mainly consists of JSP files. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

17 comments:

  1. Hi I have a question.
    Where is the applicationContext.xml file contents?

    ReplyDelete
  2. You can find it in the source code.

    ReplyDelete
  3. I am new to Spring security. Please explain
    what is "customUserDetailsService" in above code? how is it pointing to CustomUserDetailsService class?

    ReplyDelete
  4. Hi Anon,
    krams have written
    in his applicationContext.xml
    That will load this("customUserDetailsService") service automatically.
    :)
    For more info you can read about autowiring in spring or simply serach for tag component-scan.
    :)

    ReplyDelete
  5. /* Excuse me for my english */
    First, I thank Mr. Krams for this very interesting tutorial. and i wonder if
    someone can help me by posting an updated pom.xml for this project, in fact there is some problems in the "goldin" dependency.
    thank you

    ReplyDelete
  6. evgeny-goldin.org
    Evgeny Goldin Repository
    http://evgenyg.artifactoryonline.com/evgenyg/plugins-releases-local

    ReplyDelete
  7. hi, thank you for the tutorial it was very helpful for me. Actually I am trying to implement the same concept on a PostgreSQL 9.1 database but I'm facing some difficulties to do that. I made the necessary changes related to the database class driver, POM file, persistence file and springd-data file. The web application launch correctly but when I try to log in I receive the following error:
    [ERROR] [tomcat-http--9 02:23:28] (JDBCExceptionReporter.java:logExceptions:234) ERREUR: la colonne user0_.id n'existe pas
    Position: 8; I thing it related to the mapping between Hibernate and my JDBC postgresql driver,
    how can I fic this, please?
    Thanks

    ReplyDelete
  8. PLEASE stop spreading bad practices. DO NOT USE MD5 to hash passwords.

    use org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

    ReplyDelete
  9. can you tell me how to load customUserDetailsService in appication-context.xml file. I am getting error for the same.

    ReplyDelete
    Replies
    1. Check this answer, I am sure it will help you: http://forum.springsource.org/showthread.php?99923-Cannot-find-bean-when-implementing-UserDetailsService

      Delete
  10. When I try to add Filter like this

    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy



    springSecurityFilterChain
    /*

    It prompts the following exception
    >>>>>>>>>>>>>>>>>>>>>>
    SEVERE: Exception starting filter springSecurityFilterChain
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1097)
    at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:326)
    at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:194)
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:277)
    at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:258)
    at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:382)
    at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:103)
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4650)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5306)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
    <<<<<<<<<<<<<<<<<<<<

    ReplyDelete
    Replies
    1. Where is the bean "springSecurityFilterChain" declared? I suggest you use http://pastebin.com/ when posting the code

      Delete
    2. This comment has been removed by the author.

      Delete
    3. I was struggling with the same issue. My problem was that I was building the application on top of the default Spring MVC template and used provided web.xml file. Which is not bad thing to do of course. In this approach, servlet-context.xml is loaded via init-param of a servlet and I just left it there.

      However, there are two things to realise:

      a) The root context (ContextLoaderListener) cannot see beans in the child context (servlet).

      b) Spring security config file has to be loaded BEFORE the application is started.


      All errors which are mentioned here can be solved by loading those files in Root context (in the exact same way as it is done by Mark in the tutorial :) Like that:

      http://pastebin.com/dLzD6cCf

      Delete
    4. Another short note: The only thing which is loaded in Marks tutorial in child (servlet) context is spring-servlet.xml. Where is only view resolver declaration.

      Delete
  11. Hi
    If I want two separate login pages, one for users , and one for admins, what should I do?
    how should I change spring-security.xml ?

    ReplyDelete
  12. I'm getting this error while deploying:

    Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customUserDetailsService': Injection of autowired ependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private my.anm.security.UserRepository my.anm.security.CustomUserDetailsService.userRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [my.anm.security.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    Please help. Thanks

    ReplyDelete