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<>();
}
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();
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With