从 Spring 上的当前会话获取用户信息?
Getting user information from the current session on Spring?
我一直在尝试从当前会话中获取用户信息以执行一些类似 findByUsername 的操作。我已经尝试过@AuthenticationPrinciple,但即使我用我的 UserDetails 实现来提供它,它也只是 returns null。我还尝试了 returns 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;
}
}
和 UserDetailsService;
@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 的身份验证,它可以正常工作。
您在安全上下文中获得 anonymousUser 的唯一原因是您未通过身份验证。尝试在您的 SecurityConfig 中的 hasRole("USER").
之后添加 .anyRequest().authenticated()
,然后您应该会在 SecurityContextHolder.getContext().getAuthentication()
中看到主体。这将继续使用您指定为 permitAll()
.
的方法
此外,只是一个观察,但是您配置中的 url 匹配器在 /home
上并且您的控制器指定了 /Home
.
的 GetMapping
我一直在尝试从当前会话中获取用户信息以执行一些类似 findByUsername 的操作。我已经尝试过@AuthenticationPrinciple,但即使我用我的 UserDetails 实现来提供它,它也只是 returns null。我还尝试了 returns 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;
}
}
和 UserDetailsService;
@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 的身份验证,它可以正常工作。
您在安全上下文中获得 anonymousUser 的唯一原因是您未通过身份验证。尝试在您的 SecurityConfig 中的 hasRole("USER").
之后添加 .anyRequest().authenticated()
,然后您应该会在 SecurityContextHolder.getContext().getAuthentication()
中看到主体。这将继续使用您指定为 permitAll()
.
此外,只是一个观察,但是您配置中的 url 匹配器在 /home
上并且您的控制器指定了 /Home
.