1

I'm using Spring 4.3.1.RELEASE version and it's custom Authentication Login application. But I'm facing issue

First take a look on code

CustomAuthenticationProvider.java

@Component
@Qualifier(value = "customAuthenticationProvider")
public class CustomAuthenticationProvider implements AuthenticationProvider{


public Authentication authenticate(Authentication authentication) throws     AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);


    Role r = new Role();
    r.setName("ROLE_ADMIN");
    List<Role> roles = new ArrayList<Role>();
    roles.add(r);


    Collection<? extends GrantedAuthority> authorities = roles;
    return new UsernamePasswordAuthenticationToken(user, password, authorities);
}

public boolean supports(Class<?> arg0) {
    return true;
}

}

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider);
}

//.csrf() is optional, enabled by default, if using     WebSecurityConfigurerAdapter constructor
@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/admin/**").access("hasRole('ROLE_USER')")
            .and()
            .formLogin()
            .loginPage("/login").failureUrl("/login?error")
            .usernameParameter("username").passwordParameter("password")
            .and()
            .logout().logoutSuccessUrl("/login?logout")
            .and()
            .csrf();
}
}

login.jsp Here is my Login page

  <form name="loginForm" novalidate ng-submit="ctrl.login(user)">
        <div class="form-group" ng-class="{'has-error': loginForm.username.$invalid}">
            <input class="form-control" name="username" id="username"  type="text"
                   placeholder="Username" required ng-model="user.username" />
            <span class="help-block"
                  ng-show="loginForm.username.$error.required">Required</span>
        </div>
        <div class="form-group" ng-class="{'has-error': loginForm.password.$invalid}">
            <input class="form-control" name="password" id="password" type="password"
                   placeholder="Password" required ng-model="user.password" />
            <span class="help-block"
                  ng-show="loginForm.password.$error.required">Required</span>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary pull-right"
                    value="Login" title="Login" ng-disabled="!loginForm.$valid">
                <span>Login</span>
            </button>
        </div>
    </form>

On authenticate() in CustomAuhtenticationProvider class

  1. authentication.getCredentials();
  2. authentication.getName();

both giving empty string , but I need username and password in this.

Here is IntellijIdea Debug screen shot

Here is my AngularJS Service

Service.js

  function loginUser(user) {
    var config = {
        headers: {
            'csrf_token': csrfToken
        }
    }


    var deferred = $q.defer();
    $http.post("/login", user,config)
        .then(
            function (response) {
                deferred.resolve(response.data);
            },
            function(errResponse){
                console.error('Error while creating User');
                deferred.reject(errResponse);
            }
        );
    return deferred.promise;
}
Yasir Shabbir Choudhary
  • 2,458
  • 2
  • 27
  • 31

1 Answers1

0

You are sending authentication credentials as JSON and you are using the default UsernamePasswordAuthenticationFilter that tries to retrieve the authentication credentials from the HttpServletRequest parameters.

They will always be null. You must build your own custom Filter which takes the authentication credentials from the json received in the request body instead of from http params.

Have a look at this

EDIT: The fact is that you are not getting the login credentials you sent from your Angular controller. The reason is probably that if you are sending them as json in the request body you cannot rely on the default UsernamePasswordAuthenticationFilter, as it tries to build the Authentication object reading the HttpServletRequest parameteres.

public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        String username = obtainUsername(request);
        String password = obtainPassword(request);
        ...
}

/**
     * Enables subclasses to override the composition of the password, such as by
     * including additional values and a separator.
     * <p>
     * This might be used for example if a postcode/zipcode was required in addition to
     * the password. A delimiter such as a pipe (|) should be used to separate the
     * password and extended value(s). The <code>AuthenticationDao</code> will need to
     * generate the expected password in a corresponding manner.
     * </p>
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the password that will be presented in the <code>Authentication</code>
     * request token to the <code>AuthenticationManager</code>
     */
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(passwordParameter);
    }

    /**
     * Enables subclasses to override the composition of the username, such as by
     * including additional values and a separator.
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the username that will be presented in the <code>Authentication</code>
     * request token to the <code>AuthenticationManager</code>
     */
    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }

You should extend this filter, override attemptAuthentication() method to avoid calling the obtainUsername and obtainPassword while recovering this credentials. Instead, write a custom method where you will read the ServletRequest's InputStream and parse to object using the json library you used to. I usually use jackson this way

Community
  • 1
  • 1
jlumietu
  • 6,234
  • 3
  • 22
  • 31