0

I am using spring-boot and spring-security in app. My goal is to get the user name of the currently registered user from post method. Get method is working nicely but the post method isn't working. Why? How can I solve this problem?

Test Controller

@GetMapping("/test")
public String test(Authentication authentication) {
    System.out.println(authentication.getName()); // <--------- It's working
    return "testfile";
}

@PostMapping("/test")
public String testPost(Authentication authentication) {
    System.out.println(authentication.getName()); // <--------- NOLL ERROR!
    return "testfile";
}

Error

java.lang.NullPointerException: null

User

@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private long id;
    @Column(name="mail")
    private String mail;
    @Column(name="password")
    private String password;
}

UserDAO

@Repository
public class UserDAO {
    @Autowired
    private EntityManager entityManager;
    public List<User> findAll() {
        return entityManager.unwrap(Session.class).createQuery("from User", User.class).getResultList();
    }
    public User findByMail(String mail){
        Session currentSession = entityManager.unwrap(Session.class);
        Query theQuery = currentSession.createQuery("from User where mail=:mail", User.class);
        theQuery.setParameter("mail", mail);
        List<User> users = theQuery.getResultList();
        if(users.isEmpty()){
            return new User();
        }
        return users.get(0);
    }
    public void saveOrUpdate(User user) {
        Session currentSession = entityManager.unwrap(Session.class);
        currentSession.saveOrUpdate(user);
    }
}

UserService

public interface UserService extends UserDetailsService{
    public List<User> findAll();
    public User findByMail(String mail);
    public void saveOrUpdate(User user);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private UserRoleDAO userRoleDAO;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Override
    @Transactional
    public List<User> findAll() {
        return userDAO.findAll();
    }
    @Override
    @Transactional
    public User findByMail(String mail){
       return userDAO.findByMail(mail);
    }
    @Override
    @Transactional
    public void saveOrUpdate(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userDAO.saveOrUpdate(user);
    }
    @Override
    @Transactional
    public UserDetails loadUserByUsername(String mail) throws UsernameNotFoundException {
        User user = userDAO.findByMail(mail);
        List<UserRole> userRole = userRoleDAO.findByUserId(user.getId());
        if (user == null) {
            throw new UsernameNotFoundException("Invalid username or password.");
        }
        return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(), mapRolesToAuthorities(userRole));
    }
    private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<UserRole> roles) {
        return roles.stream().map(role -> new SimpleGrantedAuthority(role.getRole())).collect(Collectors.toList());
    }
}

SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private Environment env;

@Autowired
private DataSource dataSource;

@Autowired
private UserService userService;

RedirectAuthenticationSuccessHandler redirectAuthenticationSuccessHandler = new RedirectAuthenticationSuccessHandler();

RedirectAuthenticationFailureHandler redirectAuthenticationFailureHandler = new RedirectAuthenticationFailureHandler();

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource)
            .usersByUsernameQuery(env.getProperty("my.usersbyusernamequery"))
            .authoritiesByUsernameQuery(env.getProperty("my.authoritiesbyusernamequery"));
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeRequests()
            .antMatchers("/anypage1/**").hasRole("MANAGER")
            .antMatchers("/anypage2/**").hasRole("ADMIN")
            .antMatchers("/test").hasRole("ADMIN")
            .authenticated()
            .antMatchers("/**").permitAll()
            .and()
            .formLogin().loginPage("/login").failureHandler(redirectAuthenticationFailureHandler)
            .loginProcessingUrl("/login-control").successHandler(redirectAuthenticationSuccessHandler).permitAll()
            .and()
            .logout().logoutUrl("/logout").permitAll().and().exceptionHandling().accessDeniedPage("/access-denied");
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.POST, "/anypage3").antMatchers(HttpMethod.POST, "/anypage4")
                  .antMatchers(HttpMethod.POST, "/test");
}

@Bean
public BCryptPasswordEncoder passwordEncoder()
{
    return new BCryptPasswordEncoder();
}

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
    auth.setUserDetailsService(userService);
    auth.setPasswordEncoder(passwordEncoder());
    return auth;
}

}

E G
  • 157
  • 1
  • 11

2 Answers2

0

You can get username from SecurityContextHolder

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String name = user.getUsername(); //get current logged in username

In loadUserByUsername method you can manually set the Authentication token on SecurityContextHolder and same you can use in controller

UsernamePasswordWithAttributesAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( loadUserByUsername(username), password, authorities );
    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
Abhijit
  • 374
  • 3
  • 15
  • Please refer this link.I hope it will help to resolve your issue https://stackoverflow.com/a/36936819/1838148 – Abhijit Mar 03 '19 at 12:34
  • My problem is still continuing. As a workaround, I pass the `username` on `HttpSession`. – E G Mar 03 '19 at 15:47
  • You need to set username in SecurityContextHolder while verifiying your username and password.If username is valid then set it into SecurityContextHolder and use in every controller call. – Abhijit Mar 03 '19 at 15:49
  • Can you review my codes, where am I making mistake? :) – E G Mar 03 '19 at 17:12
0
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.POST, "/anypage3").antMatchers(HttpMethod.POST, "/anypage4")
                  .antMatchers(HttpMethod.POST, "/test");
}

You ignore /test in post method, so it will not be filtered by spring security filter, try to remove this.

chaoluo
  • 2,596
  • 1
  • 17
  • 29