从 Spring 的当前会话中获取用户信息?

Posted

技术标签:

【中文标题】从 Spring 的当前会话中获取用户信息?【英文标题】:Getting user information from the current session on Spring? 【发布时间】:2021-06-16 05:28:36 【问题描述】:

我一直在尝试从当前会话中获取用户信息来执行一些类似 findByUsername 的操作。我已经尝试过@AuthenticationPrinciple,但即使我用我的 UserDetails 实现来提供它,它也只是返回 null。我也尝试过返回anonymousUser(?) 的SecurityContextHolder 方法。无论哪种方式都没有得到想要的结果。尝试了到目前为止我在互联网上可以找到的所有解决方案,但没有运气。 控制器;

@Controller
public class Home 

    EntryService entryService;

    public Home(EntryService entryService) 
        this.entryService = entryService;
    


    @GetMapping("/Home")
    public String registration(Entry entry, Model model) 
        //See what it returns
        System.out.println(getUsername());
        List<Entry> entries = new ArrayList<>(entryService.getAllEntries());
        model.addAttribute("entryList", entries);
        model.addAttribute("entry", entry);

        return "/home";
    


    public String getUsername() 
        SecurityContext context = SecurityContextHolder.getContext();
        Authentication authentication = context.getAuthentication();
        if (authentication == null)
            return null;
        Object principal = authentication.getPrincipal();
        if (principal instanceof UserDetails) 
            return ((UserDetails) principal).getUsername();
         else 
            return principal.toString();
        
    


安全性;

@Configuration

public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    

    @Autowired
    public DetailsService detailsService() 
        return new DetailsService();
    

    protected void configure(HttpSecurity http) throws Exception 

        http.
                authorizeRequests().
                antMatchers("/register").
                permitAll().
                antMatchers("/home").
                hasRole("USER").
                and().
                csrf().
                disable().
                formLogin().
                loginPage("/").
                permitAll().
                passwordParameter("password").
                usernameParameter("username").
                defaultSuccessUrl("/home").
                failureUrl("/error").
                and().
                logout().
                logoutUrl("/logout");
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(detailsService()).passwordEncoder(passwordEncoder());
    


用户详情;

public class UserDetail implements UserDetails 

    private final String username;
    private final String password;
    private final boolean active;
    private final List<GrantedAuthority> roles;

    public UserDetail(User user) 
        this.username = user.getUserName();
        this.password = user.getPassword();
        this.active = user.getActive();
        this.roles = Arrays.stream(user.getRole().toString().split(",")).
                map(SimpleGrantedAuthority::new).
                collect(Collectors.toList());
    

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() 
        return roles;
    

    @Override
    public String getPassword() 
        return password;
    

    @Override
    public String getUsername() 
        return username;
    

    @Override
    public boolean isAccountNonExpired() 
        return true;
    

    @Override
    public boolean isAccountNonLocked() 
        return true;
    

    @Override
    public boolean isCredentialsNonExpired() 
        return true;
    

    @Override
    public boolean isEnabled() 
        return active;
    

和UserDetailsS​​ervice;

@Service
public class DetailsService implements UserDetailsService 

    @Autowired
    UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException 
        Optional<User> user = userRepository.findByUserName(s);
        user.orElseThrow(() -> new UsernameNotFoundException("User not found"));
        return user.map(UserDetail::new).get();
    

顺便说一句,使用基于 JPA 的身份验证,它可以按需要工作。

【问题讨论】:

【参考方案1】:

您会在安全上下文中获得anonymousUser 的唯一原因是您未经过身份验证。尝试在 SecurityConfig 中的 hasRole("USER"). 之后添加 .anyRequest().authenticated(),然后您应该会在 SecurityContextHolder.getContext().getAuthentication() 中看到主体。这将继续使用您指定为 permitAll() 的方法。

另外,只是一个观察,但您的配置中的 url 匹配器位于 /home 上,并且您的控制器指定了 /Home 的 GetMapping。

【讨论】:

好吧,看来我在“使用基于 JPA 的身份验证 btw 并且它可以按需要工作”时错了。部分。只是尝试在登录表单中输入一些随机文本,然后猜猜是什么?它只是让我进去。有点尴尬的是没有注意到整个身份验证过程失败了。修复后一切都按预期工作。感谢您的回答! 我们都去过!

以上是关于从 Spring 的当前会话中获取用户信息?的主要内容,如果未能解决你的问题,请参考以下文章

在 JAVA 中通过身份验证后如何获取 okta 用户详细信息/当前会话

Spring:保存登录的用户会话

如何从 php 中的当前会话中获取 csv 文件?

Spring 3.1:处理会话超时

怎样获取当前登录用户的ID

如何获取其他系统登录的用户信息