Максималы безопасности пружины не работают при использовании пользовательского фильтраJAVA

Программисты JAVA общаются здесь
Anonymous
Максималы безопасности пружины не работают при использовании пользовательского фильтра

Сообщение Anonymous »

Среда: < /p>

Spring Boot: 3.2.2. < /li>
Spring Security: 6.2.1 < /li>
< /ul>
Я в настоящее время использую пользовательский фильтр для поддержки форматированных данных JSON в запросах. Я также хочу использовать MaximumSessions , чтобы ограничить пользователя, который может одновременно войти в браузер.

Код: Выделить всё

    @Bean
public LoginFilter loginFilter(AuthenticationManager authenticationManager) throws Exception {
LoginFilter loginFilter = new LoginFilter();
loginFilter.setFilterProcessesUrl("/doLogin");
loginFilter.setAuthenticationManager(authenticationManager);
loginFilter.setSecurityContextRepository(new DelegatingSecurityContextRepository(
new RequestAttributeSecurityContextRepository(),
new HttpSessionSecurityContextRepository()
));
loginFilter.setAuthenticationSuccessHandler((request, response, authentication) -> {
...
});
loginFilter.setAuthenticationFailureHandler((request, response, exception) -> {
...
});

ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
strategy.setMaximumSessions(1);
loginFilter.setSessionAuthenticationStrategy(strategy);

return loginFilter;
}

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

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

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, LoginFilter loginFilter) throws Exception {
httpSecurity
.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(true))
.addFilterAt(new ConcurrentSessionFilter(sessionRegistry(), event -> {
HttpServletResponse resp = event.getResponse();
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(401);
PrintWriter out = resp.getWriter();
out.write("Already logged in on another device.");
out.flush();
out.close();
}), ConcurrentSessionFilter.class)
.addFilterAt(loginFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(
requests -> requests
.requestMatchers("/css/**", "/js/**", "/images/**", "/getVerifyCode").permitAll()
.requestMatchers("/error").permitAll()
.anyRequest().authenticated()
)
.logout(logout -> logout.logoutUrl("/doLogout")
.logoutSuccessHandler((request, response, authentication) -> {
...
})
)
.csrf(csrfConfigurer -> csrfConfigurer.disable())
.exceptionHandling(exceptionHandler -> exceptionHandler.authenticationEntryPoint((request, response, authException) -> {
log.error(authException);
}));

return httpSecurity.build();
}

А вот код логинфильтера

Код: Выделить всё

@Log4j2
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
private final ObjectMapper objectMapper;
private SessionRegistry sessionRegistry;

public LoginFilter() {
super();
objectMapper = new ObjectMapper();
}

@Autowired
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}

String verifyCode = (String) request.getSession().getAttribute("verify_code");
Map  requestParameters = new HashMap();
if (MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType())) {
requestParameters = extractRequestParametersFromJson(request);
} else {
requestParameters = extractRequestParametersFromForm(request);
}

String code = requestParameters.get("code");
checkoutVerifyCode(code, verifyCode);

String username = requestParameters.get(getUsernameParameter());
String password = requestParameters.get(getPasswordParameter());

username = username != null ? username.trim() : "";
password = password != null ? password : "";
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
this.setDetails(request, authRequest);

sessionRegistry.registerNewSession(request.getSession().getId(), authRequest.getPrincipal());
return this.getAuthenticationManager().authenticate(authRequest);
}
}

< /code>
Я новичок в Spring Security, поэтому я не уверен, что конфигурация неверна или если бы не хватает деталей.

Если кто -то может указать на проблему, я бы очень ценил это. ConcurrentsessionControLoAuthenticationStrategy#Onauthentication 
будет вызван, и внутри этого метода находится SessionRegistryImpl#getAllsessions . Inside this method, it will call the this.principals.get(principal) method, where principals is a ConcurrentMap and principal is an Object used as the map's key.
The principal actually is my custom User class and has overridden equals() and hashcode () . Тем не менее, странно то, что когда я устанавливаю точку останова на равном () , она показывает, что параметр equals () является объектом строки . Я не понимаю, почему карта использует объект пользователя в качестве ключа, но существует объект строки в equals () .
Эта странная ситуация происходит только тогда, когда я использую свой пользовательский фильтр, который расширяет usernamepasswordauthenticationfilter . Если я использую по умолчанию httpsecurity#formlogin и установите SessionManagement , он работает нормально.
При использовании httpsecurity#formlogin , параметр equals () показывает, что тип - это пользователь . Я хотел бы знать, что вызывает разницу от httpsecurity#formlogin и моего пользовательского фильтра.

Подробнее здесь: https://stackoverflow.com/questions/779 ... tom-filter

Вернуться в «JAVA»