Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot: Get current user's username

I am trying to get the current logged in username using Spring's security but the Principal object returns null.

This is my REST controller method:

@RequestMapping("/getCurrentUser")
public User getCurrentUser(Principal principal) {

    String username = principal.getName();
    User user = new User();
    if (null != username) {
        user = userService.findByUsername(username);
    }

    return user;
}

NB: I am running Spring boot 1.5.13 and spring security 4.2.6

  • This is my security config class:

    @Configuration
    
    @EnableWebSecurity
    
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
    
        @Autowired
        private Environment env;
    
        @Autowired
        private UserSecurityService userSecurityService;
    
        private BCryptPasswordEncoder passwordEncoder() {
            return SecurityUtility.passwordEncoder();
        }
    
        private static final String[] PUBLIC_MATCHERS = {
                "/css/**",
                "/js/**",
                "/image/**",
                "/book/**",
                "/user/**"
        };
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().cors().disable().httpBasic().and().authorizeRequests()
            .antMatchers(PUBLIC_MATCHERS).permitAll().anyRequest().authenticated();
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public HttpSessionStrategy httpSessionStrategy() {
            return new HeaderHttpSessionStrategy();
        }
    }
    
  • This is my user security service class:

    @Service
    
    public class UserSecurityService implements UserDetailsService {
    
    private static final Logger LOG = LoggerFactory.getLogger(UserSecurityService.class);
    
        @Autowired 
        private UserRepository userRepository;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository.findByUsername(username);
            if(null == user) {
                LOG.warn("Username {} not found", username);
                throw new UsernameNotFoundException("Username "+username+" not found");
            }
            return user;
        }
    }
    
  • this is my user class:

    @Entity
    
    public class User implements UserDetails, Serializable {
    
        private static final long serialVersionUID = 902783495L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="Id", nullable=false, updatable = false)
        private Long id;
    
        private String username;
        private String password;
        private String firstName;
        private String lastName;
    
        private String email;
        private String phone;
        private boolean enabled = true;
    
        @OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
        @JsonIgnore
        private Set<UserRole> userRoles = new HashSet<>();
    }
    
like image 620
sumit maske Avatar asked May 15 '18 16:05

sumit maske


2 Answers

There are multiple ways to do this.

Using SecurityContextHolder

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();

Using Principal from a Controller

@RequestMapping(value = "/myusername", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Principal principal) {
    return principal.getName();
}

From HttpServletRequest

@RequestMapping(value = "/myusername", method = RequestMethod.GET)
@ResponseBody
public String getUsername(HttpServletRequest req) {
    return req.getUserPrincipal.getName();
}
like image 185
pgardunoc Avatar answered Sep 30 '22 20:09

pgardunoc


The previous answer should work fine, if using spring web MVC controllers you can also have it injected into your controllers automatically out of the box using springs default method argument resolvers (org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver)

A controller can do:

@RestController
public class AcceptConnectionController {

    @PostMapping(value = "/")
    public void controllerMethod(@AuthenticationPrincipal final MyPrincipal user) {
        //...
    }

}

In the example above, MyPrincipal extends org.springframework.security.authentication.AbstractAuthenticationToken You can then pass this principal to your service layer.

like image 23
David Avatar answered Sep 30 '22 20:09

David