17

Simple question, I just need a pointer in the right direction:

I have a simple Spring MVC/Spring Security webapp. Initially I set up Spring Security so that the default login page shows and authenticates properly (I implemented the UserDetailsService with the DaoAuthenticationProvider to do this).

Next step: replace the default spring login page with my login page and post the credentials.

But what do I do with the submitted login credentials? I assume I post the form to a controller, verify the credentials, but I'm not clear what the right step is after that. E.g.:

  • Am I calling a method of AuthenticationManager?
  • Do I need to define a bean for this?
  • Is there an interface/service I need to implement like an AuthenticationEntryPoint or something?

I've hit the docs 3 times over and don't quite follow them. I know this is dirt simple, so I just need to hear how the process should flow.

David Parks
  • 30,789
  • 47
  • 185
  • 328
  • What are you trying to achieve? Why can't you just configure Spring Security to use your own form instead of the default one? – axtavt Nov 01 '10 at 12:27
  • Ah yes, I can do this, it was how that was killing me. :) There's many ways to do something in Spring and I got lost between the myriad of options. Ultimately I just needed a more clear understanding of how to use . I hadn't realized that it would actually intercept requests on the login-processing-url path and handle them, I was trying to create my own controller to handle the login form requests (an unnecessary step for a simple form login). – David Parks Nov 02 '10 at 02:24

6 Answers6

20

I'll add a clarifying answer for anyone reading this in the future:

When you define the tag in spring security it will handle the login for you, I'll go over how it works in detail (wish it were this detailed in the docs):

<security:http auto-config="true">
    <security:form-login login-page="/login"
         login-processing-url="/postlogin"
         default-target-url="/myaccount"
         authentication-failure-url="/login?loginError=true" />
    <security:logout logout-url="/logout" />
</security:http>

The login-page is the url of the login page. You should have a controller (or static HTML page) that serves this page, it's your pretty login form.

The login-processing-url is a URL which the form-login component handles. It's as if the form-login component implemented its own controller for this page. You should post your form to this page. You also need to know to name your username/password parameters "j_username" and "j_login"

Beyond this, and the rest of the reasonably obvious options above, you should have implemented a UserDetailsService - that is, create a class and implement the interface UserDetailsService which gets, and returns, a UserDetails object (username/password) for a given username - and provide that UserDetails object with the rest of the security configuration:

<security:authentication-manager>
        <security:authentication-provider ref="daoAuthenticationProvider" />
</security:authentication-manager>

<bean id="daoAuthenticationProvider"
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider" >
    <property name="userDetailsService" ref="myAuthorizationService" />
</bean>
DJS
  • 15
  • 5
David Parks
  • 30,789
  • 47
  • 185
  • 328
  • If you don't specify the login-processing-url, the login-page value will be used by default, so the login form has to be posted there. (Spring Security 3.2.4) – xtian Jun 14 '14 at 11:53
  • 2
    Note that in Spring Security 4+ the username/password parameters now default to "username" and "password" – Dave Richardson Jun 10 '15 at 10:48
  • 1
    What is the use of the `default-target-url` attribute? – Sajib Acharya Apr 11 '16 at 06:47
  • @DaveRlz is possible to append the username to the `authentication-failure-url` ? e.g. `authentication-failure-url="/login?loginError=true&username=getUser()` – Philip K. Adetiloye Jul 23 '19 at 22:39
11

Spring Security reference documentation outlines the basic processing flow in 5.4 Authentication in a Web Application. There is point #6:

Next the server will decide whether or not the presented credentials are valid. If they're valid, the next step will happen. If they're invalid, usually your browser will be asked to try again (so you return to step two above).

...

Spring Security has distinct classes responsible for most of the steps described above. The main participants (in the order that they are used) are the ExceptionTranslationFilter, an AuthenticationEntryPoint and an “authentication mechanism”, which is responsible for calling the AuthenticationManager which we saw in the previous section.

I have to admit, the documentation here is a bit confusing so I will give you some more pointers - the "authentication mechanism" mentioned here is the thing you are after, it is responsible for processing the credentials that the browser is sending.

As the details of attaching the credentials to HTTP request(s) vary greatly among different authentication methods (form data vs. plain headers vs. digest headers), there is no common "authentication mechanism" - instead, each method implements its own mechanism and in the case of web-based authentication, it is typically a special filter that you have to configure in web.xml.

In your case, you are most probably interested in UsernamePasswordAuthenticationFilter - this is used for processing basic form-based login information. The contract between your custom login form and the filter is the URL (where form is posted) + username and password field names:

The login form simply contains j_username and j_password input fields, and posts to the URL that is monitored by the filter (by default this is /j_spring_security_check).
Neeme Praks
  • 8,956
  • 5
  • 47
  • 47
  • Thank you for the detailed explaination. It helped me finally understand how the tag works. I didn't understand that it essentially worked as a controller where it actually handles requests posted to the login-processing-url, and that I needed to pass parameters named j_username, and j_password – David Parks Nov 02 '10 at 02:21
  • do you care help me with a similar topic? I trying implement a custom login processing method with java config, and I stucked with this problem: http://stackoverflow.com/questions/22738738/my-application-with-spring-security-dont-go-beyond-login-page. Any help should be very thankful. – Kleber Mota Mar 30 '14 at 14:57
2
<security:http auto-config="true">
  <security:form-login login-page="/login"
   login-processing-url="/postlogin"
    default-target-url="/myaccount"
     authentication-failure-url="/login?loginError=true" />
  <security:logout logout-url="/logout" />
</security:http>

login-page is the login form URL login-processing-url is the url where login form is submitted. Spring will give a self call the authentication-manager mapped by you in security.xml file.

Process

  1. You need to write a class that implements org.springframework.security.authentication.AuthenticationProvider with overriden method Authentication authenticate(Authentication authentication)
  2. Second class that extends org.springframework.security.core.userdetails.UserDetailsService with a overridden method loadUserByUsername(String username)
  3. The second class form where you can call your DAO and validate user with database fetching username and password.
  4. In Authentication authenticate(Authentication authentication) you will compare the password and return success failure your are done.
2

See the posting by limc in response to Ritesh's answer at Configuring Spring Security 3.x to have multiple entry points Look at the sections titled:

UPDATE 01-29-2011 - @Ritesh's technique
UPDATE - SOLUTION to @Ritesh's technique

It is a concise, advanced good example of how you can customize the login process in Spring Security

Community
  • 1
  • 1
gunalmel
  • 411
  • 6
  • 7
1

If you're using a JDBC accessible database, then you could use the following authentication-provider and avoid creating a custom one. It cuts down the code required to 9 lines of XML:

<authentication-provider>
    <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password from users where username=?" authorities-by-username-query="select u.username, r.authority from users u, roles r where u.userid = r.userid and u.username =?" />
</authentication-provider>

You can then setup your dataSource as follows

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/DB_NAME" />
    <property name="username" value="root" />
    <property name="password" value="password" />
</bean>

Have a look at this post: http://codehustler.org/blog/spring-security-tutorial-form-login/ It covers everything you need to know about customising Spring Security form-login.

Alessandro Giannone
  • 885
  • 1
  • 10
  • 27
1

We are talking about the same problem more and less, this is my approach let's see what people will say.

Community
  • 1
  • 1
danny.lesnik
  • 18,479
  • 29
  • 135
  • 200
  • Are you using Spring Security there? I got lost on the form login, but with the basic default login page provided by Spring Security (a separate bundle from the Spring Framework) you need to implement a UserDetails service, and those docs specifically calls out against storing any user information in the session (they should be stored in a UserDetails object which is handled by the SecurityContextHolder). You would access everything via SecurityContextHolder, and determine if the authenticated user has a specific role that you defined for it in the UserDetails object. – David Parks Nov 01 '10 at 09:37
  • Actually, I'm not using any Spring Security framework currently, but I may be it's a good idea. I'm not storing anything on the HTTP Session because as far as I understand it's not thread-safe. I'm storing it on Session level. I have not decided yet whether it worth to implement Spring Security and would like to listen what the gurus have to say. – danny.lesnik Nov 01 '10 at 09:48
  • Spring security is nice, and not too hard to implement. For me (I'm in almost exactly the same scenario as you) it seemed logical enough. You're probably going to fuss with doing it yourself nearly as much as you would learning the extra framework, you'll just spend more time up front than over the long run. After its in there it's really easy to apply a wide variety of security options. I'd suggest reading the docs at least. – David Parks Nov 01 '10 at 10:13