2

Я использую spring security3 и spring mvc3 для создания веб-проекта. Будет страница с именем index.jsp, имя пользователя входа и счетчик онлайн-пользователей будут отображаться на в верхней части этого экрана. Есть 2 способа входа в систему:Регистрация пользователей с sessionRegistry не работает при ручной аутентификации

  1. от страницы входа, используйте пост конфигурации по умолчанию с помощью «j_spring_security_check»
  2. АЯКС входа с аутентификацией вручную

Когда я использую страницу входа для входа в индекс странице, как счет онлайн-информации, так и имя пользователя отображаются правильно. Но когда я использую ajax login (ручная аутентификация), возникает проблема: подсчет онлайн-пользователя не обновляется, он всегда отображает 0, пока имя пользователя может отображаться правильно. Часть контроллера:

@Autowired 
@Qualifier("authenticationManager") 
AuthenticationManager authenticationManager; 
@Autowired 
SecurityContextRepository repository; 

@RequestMapping(value="/ajaxLogin") 
@ResponseBody 
public String performLogin(
     @RequestParam("j_username") String username, 
     @RequestParam("j_password") String password, 
     HttpServletRequest request, HttpServletResponse response) { 
      UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); 
      try { 
       Authentication auth = authenticationManager.authenticate(token); 
       SecurityContextHolder.getContext().setAuthentication(auth); 
       repository.saveContext(SecurityContextHolder.getContext(), request, response); 
       logger.info("Authentication successfully! "); 
       return "{\"status\": true}"; 
      } catch (BadCredentialsException ex) { 
       return "{\"status\": false, \"error\": \"Bad Credentials\"}"; 
      } 
} 

весна-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" 
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/security 
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"> 

<http auto-config="true" use-expressions="true">  
    <intercept-url pattern="/login" access="permitAll" /> 
    <intercept-url pattern="/index" access="permitAll" /> 
    <form-login login-page="/login" default-target-url="/index" 
     authentication-failure-url="/loginfailed" /> 
    <logout logout-success-url="/logout" /> 

    <session-management invalid-session-url="/index"> 
     <concurrency-control max-sessions="1" 
      error-if-maximum-exceeded="false" /> 
    </session-management> 
</http> 

<authentication-manager alias="authenticationManager"> 
    <authentication-provider> 
     <jdbc-user-service data-source-ref="dataSource" 

      users-by-username-query=" 
       select login_id,login_pwd, is_enabled 
       from t_user where login_id=?" 

      authorities-by-username-query=" 
       select u.login_id, r.authority from t_user u, t_roles r 
       where u.u_id = r.u_id and u.login_id =? " /> 
    </authentication-provider> 
</authentication-manager> 

метод я использовал, чтобы рассчитывать на сайте пользователей Логин:

public class BaseController { 
    protected Logger logger = Logger.getLogger(this.getClass()); 

    @Autowired 
    SessionRegistry sessionRegistry; 

    @ModelAttribute("numUsers") 
    public int getNumberOfUsers() { 
     logger.info("in getNumberOfUsers() ..."); 
     return sessionRegistry.getAllPrincipals().size(); 
    } 
} 

Код используется для отображения логин имя пользователя:

<div> 
     <security:authorize ifAllGranted="ROLE_USER"> 
      <p><a href="#TODO">Welcome <security:authentication property="principal.username" />!</a> &nbsp;&nbsp;&nbsp; 
      <a href="<c:url value="/j_spring_security_logout" />">Logout</a></p> 
     </security:authorize> 
    </div> 

код, используемый, чтобы показать подсчет зарегистрированных пользователей:

<div style="color:#3CC457"> 
     ${numUsers} user(s) are logged in! 
    </div> 

Я думаю, потому что, когда я вручную аутентификации, весна безопасности не создать новую сессию для пользователя. Я проверяю его, создавая собственный SessionCounterListener.

public class SessionCounterListener implements HttpSessionListener { 
private Logger logger = Logger.getLogger(this.getClass()); 
private static int totalActiveSessions; 

public static int getTotalActiveSession(){ 
     return totalActiveSessions; 
} 

@Override 
public void sessionCreated(HttpSessionEvent event) { 
     totalActiveSessions++; 
     logger.info("sessionCreated - add one session into counter" + event.getSession().getId()); 
} 

@Override 
public void sessionDestroyed(HttpSessionEvent event) { 
     totalActiveSessions--; 
     logger.info("sessionDestroyed - deduct one session from counter" + event.getSession().getId()); 
} 

}

Ниже ключ содержимого файла журнала для последовательности действий: нормальный логин -> нормальный выход из системы -> Аякса Войти -> Аякса выход из системы.

sessionDestroyed - deduct one session 1spueddcmdao019udc43k3uumw 
sessionCreated - add one session 14nro6bzyjy0x1jtvnqjx31v1 
sessionDestroyed - deduct one session 14nro6bzyjy0x1jtvnqjx31v1 
sessionCreated - add one session e6jqz5qy6412118iph66xvaa1 

Фактически, ajax login/logout не дает никакого выхода.

Итак, как я могу получить правильный счет пользователя? И почему разные способы аутентификации имеют разный метод работы с сеансом? Любая помощь будет оценена.

+0

Использование SessionUtils. См. Например: http://stackoverflow.com/questions/1013032/programmatic-use-of-spring-security – Ritesh

ответ

0

В вашей весне spring-security.xml файла URL-адрес для аутентификации AJAX (/ajaxLogin) явно не разрешен. Таким образом, запрос должен быть заблокирован весной. Я хотел бы предложить, чтобы добавить это:

<intercept-url pattern="/ajaxLogin" access="permitAll" /> 
+0

Здравствуйте @LaurentG, я попробовал ваше предложение, но оно не работает. Когда я использую/ajaxLogin, «Welcome [email protected]» уже отображается, но только количество пользователей показывает 0. См. Журнал, система не будет вызывать sessionCreated (событие HttpSessionEvent). После проверки подлинности вручную система будет использовать один и тот же идентификатор сеанса, в то время как обычный вход автоматически создаст новый идентификатор сеанса после успешной проверки подлинности. –

3

Как вы вручную добавлять Principal к SecurityContext, это не добавит пользователю SessionRegistry. Вам нужно добавить сеанс пользователя в SessionRegistry вручную.

SecurityContextHolder.getContext().setAuthentication(auth); 
sessionRegistry.registerNewSession(request.getSession().getId(), auth.getPrincipal()); 

Надеюсь, это поможет!