Konstantin
Konstantin

Reputation: 21

Spring Authentication return null

SecurityContextHolder in my app is always returning null Authentication on action in my web-page I'm trying to get authenticated user to get his name from DB and to store new record with appropriate user. Here is simple code:

@Controller
public class SomeController {


    @Autowired
    EngineerService engineerService;

    @Autowired
    OtherService otherService;

    @MessageMapping("/saveSomething")
    public String saveSomething(String input){
        String userName = SecurityContextHolder.getContext().getAuthentication().getName();
        Engineer engineer = engineerService.getByLogin(userName);
        otherService.SaveNewEntity(input, engineer);
        return "trigger";
    }
}

But first string in this code always cause nullPointerException, cause getAuthentication() return null. here is my SecurityController:

@Controller
public class SecurityController {

    @RequestMapping(value="/", method= RequestMethod.GET)
    public String login(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication.isAuthenticated()){
            return "redirect:/main.html";
        }else{
            return "redirect:/error";
        }
    }

    @RequestMapping(value="/user", method = RequestMethod.GET)
    @ResponseBody
    public User getUser() {
        User user = new User();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            String name = auth.getName();
            user.setName(name);
        }
        return user;
    }
}

I've tried to use getUser() method, but it always return string "user", even if I login with user "admin". Here is SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    DataSource dataSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("pass").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("user").password("pass").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/css/signin.css").permitAll()
                .antMatchers("/webjars/bootstrap/css/bootstrap.min.css").permitAll()
                .anyRequest().authenticated()
                .and().formLogin().loginPage("/login.html").permitAll();

    }
}

Unfortunately, this code not mine and I've spent whole day playing around SecurityContextHolder. I've understood that needed userName located in another thread, but I can't understand, how to get right Context to get right Authentication object.

Upvotes: 1

Views: 2937

Answers (1)

Konstantin
Konstantin

Reputation: 21

So, the only thing needed was to add Principal with annotation to method.

@Controller
public class SomeController {


    @Autowired
    EngineerService engineerService;

    @Autowired
    OtherService otherService;

    @MessageMapping("/saveSomething")
    public String saveSomething(@AuthenticationPrincipal Principal user, String input){
        String userName = user.getName();
        Engineer engineer = engineerService.getByLogin(userName);
        otherService.SaveNewEntity(input, engineer);
        return "trigger";
    }
}

Upvotes: 1

Related Questions