Getting logged in users with sessionRegistry not work when manually authenticate

我的未来我决定 提交于 2019-12-22 12:32:29

问题


I use spring security3 and spring mvc3 to build an web project. There is page called index.jsp, login user name and online user count will be displayed on the top of this screen. There are 2 ways to login the system:

  1. from login page, use default configuration post by 'j_spring_security_check'
  2. ajax login with manually authentication

When I use login page to login into index page, both of count of online information and user name show correctly. But when I use ajax login (manually authenticate), problem occurs: count of online user don't updated, it always displaying 0 while user name can show properly. Part of the controller:

@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\"}";
            }
}

spring-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>

Method I used to get online login user count:

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();  
    }  
}

Code used to show login user name:

<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>

code used to show count of logged in users:

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

I guess that because when I manually authenticate, spring security not create new session for the user. I validate it by write customized 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());  
}   

}

Below is key content of log file for the action sequence: normal login -> normal logout -> ajax login -> ajax logout.

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

Actually, ajax login/logout not give any output.

So now, how can I get correct login user count? And why the different authenticate ways has different method to deal with session? Any help will be appreciated.


回答1:


As you are manually adding Principal to SecurityContext, it will not add user to SessionRegistry. You need to add user session to SessionRegistry manually.

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

Hope it helps!!




回答2:


In your Spring spring-security.xml file, the URL for the AJAX authentication (/ajaxLogin) is not explicitly allowed. Thus the request should be blocked by Spring. I would suggest to add this:

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


来源:https://stackoverflow.com/questions/18271727/getting-logged-in-users-with-sessionregistry-not-work-when-manually-authenticate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!