问题
I am trying to add Facebook authorization using Spring Security in Spring Boot app. Currently, my problem is extracting data from Principal.
Here is my security config:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (HttpSecurity http) throws Exception {
http
.csrf().disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.deleteCookies("JSESSIONID")
.clearAuthentication(true)
.logoutSuccessUrl("/").permitAll();
}
@Bean
public PrincipalExtractor facebookPrincipalExtractor(){
return new FacebookPrincipalExtractor();
}
}
and principal extractor:
public class FacebookPrincipalExtractor implements PrincipalExtractor {
@Autowired
UserService userService;
@Override
public Object extractPrincipal(Map<String, Object> map) {
String name = (String) map.get("name");
String id = (String) map.get("id");
User user = userService.findOne(id);
if (user == null) {
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
String token = ((OAuth2AuthenticationDetails) authentication.getDetails()).getTokenValue();
user = new User();
FacebookClient facebookClient = new DefaultFacebookClient(token, Version.VERSION_2_10);
JSONObject object = facebookClient.fetchObject("me", JSONObject.class);
// userService.createUser(object);
}
return user;
}
}
After login, the Map<String, Object> map
contains only the name and id. Call to securityContext.getAuthentication()
returns null
.
Moreover, if I create something similar to the endpoint and pass the Principal
there as a parameter, then this will work. Example:
@RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
The principal
will contain all the necessary data.
In this regard, 2 questions:
- Why security context does not contain authentication?
- Where does the
principal
come from if it is passed as a parameter to a method?
This is what the debug looks like inside
回答1:
Although SecurityContextHolder.getContext()
is never null the authentication it contains is cleared once a request is completed. What this means is that if you try to access it during a process which goes through the spring web security it will be there. But as soon as the request finishes the following gets logged
SecurityContextHolder now cleared, as request processing completed
and the authentication is set to null. Any attempts to access it directly through the SecurityContext outside of an http request will result in a null.
回答2:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); authentication.getPrincipal();
use nested call for getting authentication object and then getPrincipal(); will return current loggedin user details
来源:https://stackoverflow.com/questions/60288854/authentication-is-null-on-the-securitycontextholder-getcontext