【问题标题】:Authentication is null on the SecurityContextHolder.getContext();SecurityContextHolder.getContext() 上的身份验证为空;
【发布时间】:2020-06-02 22:39:23
【问题描述】:

我正在尝试在 Spring Boot 应用程序中使用 Spring Security 添加 Facebook 授权。目前,我的问题是从 Principal 中提取数据。

这是我的安全配置:

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();
    }
}

和主要提取器:

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;
    }
}

登录后,Map&lt;String, Object&gt; map 仅包含名称和 ID。调用securityContext.getAuthentication() 返回null

此外,如果我创建类似于端点的东西并将Principal 作为参数传递在那里,那么这将起作用。示例:

@RequestMapping("/user")
public Principal user(Principal principal) {
    return principal;
}

principal 将包含所有必要的数据。

在这方面,2个问题:

  1. 为什么安全上下文不包含身份验证?
  2. 如果principal 作为参数传递给方法,它来自哪里?

这就是调试内部的样子

【问题讨论】:

标签: java spring-boot facebook-graph-api spring-security


【解决方案1】:

尽管SecurityContextHolder.getContext()从不 null,但一旦请求完成,它包含的身份验证就会被清除。这意味着,如果您尝试在通过 Spring Web 安全的过程中访问它它将在那里。但是一旦请求完成,就会记录以下内容

SecurityContextHolder 现在清除,因为请求处理完成

并且身份验证设置为空。任何尝试在 http 请求之外直接通过 SecurityContext 访问它都会导致 null

【讨论】:

  • 在我的情况下,从 MVC 迁移到 Webflux 导致了这种行为。
【解决方案2】:

身份验证身份验证 = SecurityContextHolder.getContext().getAuthentication(); authentication.getPrincipal();

使用嵌套调用获取身份验证对象,然后 getPrincipal();将返回当前登录用户的详细信息

【讨论】:

  • authentication=null,如果我调用 authentication.getPrincipal();我会收到 NPE
  • 这个答案应该被删除
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
相关资源
最近更新 更多