1

I'm using Spring MVC and Spring Security for the authentication. I'm doing the login with username and password but I would like to send two more parameters. Is there any way to do that?

This is the login form:

<form action="#" th:action="@{/auth/login}" th:object="${loginBean}"  method="post">  
    <input type="hidden" th:field="*{timezone}" th:value="*{timezone}" />
    <input type="hidden" th:field="*{language}" th:value="*{language}" />
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <input type="text" placeholder="Email" th:field="*{username}" required="required" 
        title="Email pattern does not match" pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$"/>
    <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}">Email Error</span>
    <input type="password" placeholder="Password" th:field="*{password}" required="required" />
    <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password Error</span>
    <button type="submit" id="login-button">Login</button>                      
</form>

I would like to send the timezone and language in the login too.

And the AuthenticationProvider:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String name = authentication.getName();

        // You can get the password here
        String password = authentication.getCredentials().toString();

        TokenDTO t = new TokenDTO();
        t.setIdioma("en-US");

        //try {

        CustomUserService  userService = new CustomUserService();

        UserDetails user =  userService.loadUser(name, password);

        if (user == null)
            throw new BadCredentialsException("Username not found.");

        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

        Authentication auth = new UsernamePasswordAuthenticationToken(user, user.getPassword(), authorities);

        return auth;     
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Is it possible to send more params in the authentications?

dur
  • 15,689
  • 25
  • 79
  • 125
Zuri
  • 312
  • 3
  • 18
  • 1
    Please refer to the below link: http://stackoverflow.com/questions/10074308/how-to-pass-an-additional-parameter-with-spring-security-login-page – nits May 24 '16 at 15:46

2 Answers2

3

1.You can create a custom filter CustomUsernamePasswordAuthenticationFilter, It will look something like this:

public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        final String languageParam = request.getParameter("language");
        request.getSession().setAttribute("language", languageParam);
        System.out.println("Filter" + languageParam);
        // You can do your stuff here
        return super.attemptAuthentication(request, response); 
    } 
}

2.In Security config create a bean for your custom filter

@Bean
public UsernamePasswordAuthenticationFilter authenticationFilter() {
    CustomUsernamePasswordAuthenticationFilter authFilter = new CustomUsernamePasswordAuthenticationFilter();
    List<AuthenticationProvider> authenticationProviderList = new ArrayList<AuthenticationProvider>();
    authenticationProviderList.add(authenticationProvider);
    AuthenticationManager authenticationManager = new ProviderManager(authenticationProviderList);
    authFilter.setAuthenticationManager(authenticationManager);
    authFilter.setUsernameParameter("username");
    authFilter.setPasswordParameter("password");
    return authFilter;
}

3.In security config configure addFilter for http, it will be something like this

@Override
protected void configure(HttpSecurity http) throws Exception {

  http.authorizeRequests()
    .antMatchers("/").permitAll()
    .antMatchers("/home").access("hasRole('ROLE_USER')")
    .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
    .antMatchers("/api/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_API')")
    .and()
    .formLogin()
    .loginProcessingUrl("/login")
    .loginPage("/loginPage")
    .failureUrl("/loginPage?error")
    .defaultSuccessUrl("/home")
    .usernameParameter("username")
    .passwordParameter("password")
    .and()
    .exceptionHandling()
    .accessDeniedPage("/Access_Denied").and()
    .addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class);


}

If you want these additional values in your controller , you can add HttpServletRequest request parameter and fetch values from session like this.

request.getSession().getAttribute("language");   
Prakash Hari Sharma
  • 1,414
  • 2
  • 17
  • 22
  • Thanks! I'm trying your solution, but custom filter isn't called when I try to log.I have added as you said in the Segurity Config. – Zuri May 25 '16 at 08:14
  • I ested it with custom authenticationProvider implementation, and it works for me, May be you need to provide custom authenticationProvider. – Prakash Hari Sharma May 25 '16 at 08:21
  • Even with a custom authentication provider, this didn't work for me. What actually did work was `@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ... }` – Axel Amthor Jun 07 '23 at 11:48
-1

You have to implement a custom Authentication and do as detailed in the post above.

Edit: In your CustomAuthenticationProvider you should return a custom Authentication object. You can achive that implementing your class that implements the Authentication interface.

Hooch
  • 487
  • 3
  • 11
  • 1
    Can you elaborate on your solution. Please describe the step in your post instead of just providing a link. OP shouldn't have to click on a link to get the answer (So if the link goes down your anwer is still relevent) – litelite May 24 '16 at 16:03