1

I am working on a Spring-MVC project in which I have Spring-security for authentication and authorization. The login mechanism works by default, just that it redirects to another page for successful or denied login.

I wanted to make this with Ajax, so I referred to some posts on SO, and made some changes, unfortunately, it is not working.

security-applicationContext.xml :

 <security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
        <security:form-login login-page="/login" username-parameter="j_username" password-parameter="j_password"
                             login-processing-url="/j_spring_security_check" default-target-url="/dashboard"
                             always-use-default-target="true" authentication-failure-url="/denied"/>
        <security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService"
                              token-validity-seconds="1209600" data-source-ref="dataSource"/>
        <security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<!--            <security:intercept-url pattern="/**" requires-channel="https"/> -->
        <security:port-mappings>
            <security:port-mapping http="80" https="443"/>
        </security:port-mappings>
        <security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>

        <security:session-management session-fixation-protection="migrateSession">
            <security:concurrency-control session-registry-ref="sessionReg" max-sessions="5" expired-url="/login"/>
        </security:session-management>
    </security:http>

    <beans:bean id="sessionReg" class="org.springframework.security.core.session.SessionRegistryImpl"/>

    <beans:bean id="rememberMeAuthenticationProvider"
                class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:constructor-arg index="0" value="_spring_security_remember_me"/>
        <beans:constructor-arg index="1" ref="userDetailsService"/>
        <beans:constructor-arg index="2" ref="jdbcTokenRepository"/>
        <property name="alwaysRemember" value="true"/>
    </beans:bean>

    <beans:bean id="jdbcTokenRepository"
                class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <beans:property name="createTableOnStartup" value="false"/>
        <beans:property name="dataSource" ref="dataSource"/>
    </beans:bean>

    <!-- Remember me ends here -->
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider user-service-ref="LoginServiceImpl">
            <security:password-encoder ref="encoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <beans:bean id="encoder"
                class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value=""/>
    </beans:bean>

    <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
        <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>
</beans>

AjaxAuthenticationSuccessHandler.java :

public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private AuthenticationSuccessHandler defaultHandler;

    public AjaxAuthenticationSuccessHandler() {

    }
    public AjaxAuthenticationSuccessHandler(AuthenticationSuccessHandler defaultHandler) {
        this.defaultHandler = defaultHandler;
    }

    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response, Authentication auth)
            throws IOException, ServletException {
        if ("true".equals(request.getHeader("X-Ajax-call"))) {
            response.getWriter().print("ok");
            response.getWriter().flush();
        } else {
            defaultHandler.onAuthenticationSuccess(request, response, auth);
        }
    }
}

Ajax code :

var form = $(this);
                       $.when(userController.login(form)).done(function(result){
   if(result == "ok"){
       window.location.href = "/dashboard";
 } else {
  alert("error");
  }
}).fail(function(response){
 alert("ups");
});

Method in usercontoller:

      this.login = function(form){
            return $.ajax({
            url: baseURL + '/j_spring_security_check',
            type: 'POST',
           data: form.serialize(),
            beforeSend: function(xhr){
                  xhr.setRequestHeader("X-Ajax-call", "true");
            }
            });
      };

I checked in firebug, username and password is sent correctly. Kindly let me know. Thank you.

We are Borg
  • 5,117
  • 17
  • 102
  • 225
  • You are no where declaring or using your `AjaxAuthenticationSuccessHandler`... – M. Deinum Feb 01 '16 at 12:33
  • @M.Deinum : I am not using it. I thought I would get it's result directly in userController.login(form). – We are Borg Feb 01 '16 at 12:36
  • How do expect that would work? You have to configure it and add it to the form -login element (and wrap the original success handler). Else it will not work. And redirect and ajax are a pain as the browser handles the 302. – M. Deinum Feb 01 '16 at 12:37
  • @M.Deinum : My JS colleague says, that the .done() function is processing the success event. the login function is returning the promise object which is handled by the done or fail handler, depending on the response of the server. the code is actually returning in the success handler but is not returning "ok" as an result – We are Borg Feb 01 '16 at 12:43
  • He is wrong... When you get a 302, this will be handled by the browser. So you won't get the result of the losing but the result of the redirect in your js `done`. So you need to use your customized success handler to prevent sending a 302. See http://stackoverflow.com/questions/199099/how-to-manage-a-redirect-request-after-a-jquery-ajax-call – M. Deinum Feb 01 '16 at 12:44
  • @M.Deinum : I am not getting a 302, even for wrong password as it shows the denied page with 200. We just checked by looking for status-code, but that didn't help due to above reasons. I thought that was the reason of using AjaxAuthenticationSuccessHandler, where I will get back proper String informing the actual status of authentication. Can you recommend correction? Thank you. – We are Borg Feb 01 '16 at 12:55
  • Correct... As that is the result of the 30[1|2] which is handled by the browser... – M. Deinum Feb 01 '16 at 12:56
  • @M.Deinum : Can you recommend any other easier strategy to solve this problem? Thank you. – We are Borg Feb 01 '16 at 12:57
  • Use a proper success and failure handling that is aware of the fact yu are using ajax. SO don't you don't get redirects but status codes (other then 30[1|2] so you can react on them. There are several answers on stack overflow already and some blogs on google. – M. Deinum Feb 01 '16 at 12:59

0 Answers0