gpt4 book ai didi

java - Spring Security with session get online users 返回空

转载 作者:行者123 更新时间:2023-12-04 11:52:50 26 4
gpt4 key购买 nike

有多个版本的相同问题,但似乎没有一个可以解决这个问题。我想从 Spring Security 获得在线用户。我知道我们需要 Autowiring SessionRegistry 并使用它。但是,它仍然不起作用。这是代码。
不确定是由于自定义用户名、密码身份验证还是由于自定义密码编码器或其他原因。一切似乎都是正确的。即使获取当前登录用户的数据也能正常工作,但未登录用户列表。
session 安全配置文件

@EnableJpaRepositories(basePackageClasses = UsersRepository.class)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SessionSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private PasswordEncoder passwordencoder;

@Autowired
private UserDetailsService userDetailsService;

@Autowired
private UsernamePasswordAuthProvider usernamepasswdauth;

@Bean
SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}

@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(usernamepasswdauth).userDetailsService(userDetailsService)
.passwordEncoder(passwordencoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.csrf().disable();
http.authorizeRequests() //
.antMatchers("/ua/*").permitAll() //
.antMatchers("/auth/*").authenticated() //
.and().requestCache() //
.requestCache(new NullRequestCache());
http.httpBasic().disable();
http.formLogin().disable();
http.logout().disable();
http
.sessionManagement()
.maximumSessions(1).sessionRegistry(sessionRegistry());
}

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}

}
密码升级程序
@Component
@Primary
public class PasswordUpgrader implements PasswordEncoder { // used to upgrade NTML password hashes to Bcrypt

private final static BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();

private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

@Autowired
JdbcTemplate jdbc;

public String encode(CharSequence rawPassword) {
byte[] bytes = NtlmPasswordAuthentication.nTOWFv1(rawPassword.toString());
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars).toLowerCase();
}

public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (encodedPassword == null || encodedPassword.length() == 0) {
return false;
}
if (encodedPassword.equals(encode(rawPassword))) {
String sql = "update user_data set password=? where password=?";
jdbc.update(sql, new Object[] { bcrypt.encode(rawPassword), encode(rawPassword) });
return true;
} else {
return bcrypt.matches(rawPassword, encodedPassword);
}
}
}
用户名PasswordAuthProvider.java
@Component
public class UsernamePasswordAuthProvider implements AuthenticationProvider {
Log logger = LogFactory.getLog(getClass());

@Autowired
private PasswordEncoder passwordencoder;

@Autowired
private UserDetailsService userDetailsService;

@Autowired
Userdata userdata;

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
String username = String.valueOf(auth.getPrincipal());
String password = String.valueOf(auth.getCredentials());
UserDetails user = userDetailsService.loadUserByUsername(username);
String encodedpassword = user.getPassword().toString();
logger.info("inside username passwd authentication");
if (encodedpassword != null && password != null && passwordencoder.matches(password, encodedpassword)) {
logger.info("inside username passwd authentication");
return new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());
}
throw new BadCredentialsException("Username/Password Incorrect");
}

public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

}
UnauthController.java
@RestController
@RequestMapping("/ua")
public class UnauthController {

@Autowired
private UsernamePasswordAuthProvider usernamepasswdauth;

@PostMapping("/login")
public Map<String, Object> login(HttpServletRequest req, @RequestBody Map<String, Object> map) {
Authentication auth = usernamepasswdauth.authenticate(new UsernamePasswordAuthenticationToken(
map.get("username").toString(), map.get("password").toString()));
SecurityContextHolder.getContext().setAuthentication(auth);
map.put("sessionid", session.getId());
return map;
}
}
验证 Controller .java
@RestController
@RequestMapping("/auth")
public class AuthController {

@Autowired
Userdata user;

@Autowired
SessionRegistry sessionregistry;

Log logger = LogFactory.getLog(getClass());

@GetMapping("/onlineusers")
public List<String> authhello(Authentication authentication) {
logger.debug(user.getEmail()); // prints current logged in user's email.
logger.debug(sessionRegistry.getAllPrincipals());//returns empty
return sessionRegistry.getAllPrincipals().stream()
.filter(u -> !sessionRegistry.getAllSessions(u, false).isEmpty()).map(Object::toString)
.collect(Collectors.toList());
}
}
尝试的方法:
  • Baeldung
  • Stackoverflow
  • StackOverflow
  • 最佳答案

    如果您仔细阅读文档 here ,写得很好(虽然很隐蔽)。问题的原因在于身份验证后处理数据的方式。在 spring 安全提供的默认身份验证中,成功身份验证后,控制通过管理 session 的过滤器传递。但是,如果您在成功进行身份验证后使用自定义身份验证并重定向用户,则该过滤器不会起作用,这就是 session 注册表中未添加 session 并返回空列表的原因。
    解决方案是将带有 session 注册表的认证策略设置到spring security的 session 管理配置中。这将导致预期的行为。
    你会发现代码更有帮助。

    方法一:
    session 的 Spring 安全配置

    http
    .sessionManagement()
    .sessionAuthenticationStrategy(concurrentSession())
    .maximumSessions(-1)
    .expiredSessionStrategy(sessionInformationExpiredStrategy())
    定义 bean
    @Bean
    public CompositeSessionAuthenticationStrategy concurrentSession() {

    ConcurrentSessionControlAuthenticationStrategy concurrentAuthenticationStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
    List<SessionAuthenticationStrategy> delegateStrategies = new ArrayList<SessionAuthenticationStrategy>();
    delegateStrategies.add(concurrentAuthenticationStrategy);
    delegateStrategies.add(new SessionFixationProtectionStrategy());
    delegateStrategies.add(new RegisterSessionAuthenticationStrategy(sessionRegistry()));

    return new CompositeSessionAuthenticationStrategy(delegateStrategies);
    }


    @Bean
    SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
    return new CustomSessionInformationExpiredStrategy("/login");
    }


    @Bean
    public SessionRegistry sessionRegistry() {
    return new SessionRegistryImpl();
    }
    这是 CustomSessionInformationExpiredStrategy.java
    public class CustomSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {

    private String expiredUrl = "";

    public CustomSessionInformationExpiredStrategy(String expiredUrl) {
    this.expiredUrl = expiredUrl;
    }

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) throws IOException, ServletException {

    HttpServletRequest request = sessionInformationExpiredEvent.getRequest();
    HttpServletResponse response = sessionInformationExpiredEvent.getResponse();
    request.getSession();// creates a new session
    response.sendRedirect(request.getContextPath() + expiredUrl);
    }

    }

    方法:2
    在 spring 安全配置中,使用方法 1 中的 concurrentSession()。
    http.sessionManagement().sessionAuthenticationStrategy(concurrentSession());
    http.addFilterBefore(concurrentSessionFilter(), ConcurrentSessionFilter.class);
    这是 CustomConcurrentSessionFilter.java
    public class CustomConcurrentSessionFilter extends ConcurrentSessionFilter {

    public CustomConcurrentSessionFilter(SessionRegistry sessionRegistry) {
    super(sessionRegistry);
    }

    public CustomConcurrentSessionFilter(SessionRegistry sessionRegistry, SessionInformationExpiredStrategy sessionInformationExpiredStrategy) {
    super(sessionRegistry, sessionInformationExpiredStrategy);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    super.doFilter(req, res, chain);
    }

    }
    还在为某事挠头吗?在 Github repo 找到工作示例.随意提出问题或贡献。

    关于java - Spring Security with session get online users 返回空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64710188/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com