手动进行身份验证时,使用sessionRegistry登录的用户无法正常工作 [英] Getting logged in users with sessionRegistry not work when manually authenticate

查看:123
本文介绍了手动进行身份验证时,使用sessionRegistry登录的用户无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用spring security3和spring mvc3构建一个Web项目.有一个名为index.jsp的页面,登录用户名和在线用户数将显示在 屏幕顶部.有两种方法可以登录系统:

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. 在登录页面上,使用"j_spring_security_check"的默认配置信息
  2. 具有手动身份验证的ajax登录

使用登录页面登录索引页面时,在线信息计数和用户名均正确显示. 但是,当我使用ajax登录(手动进行身份验证)时,会出现问题:在线用户的数量没有更新,它始终显示0,而用户名可以正确显示. 控制器的一部分:

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

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>

我猜这是因为,当我手动进行身份验证时,spring security不会为用户创建新会话.我通过编写自定义的SessionCounterListener来对其进行验证.

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

}

以下是操作序列日志文件的关键内容:正常登录->正常注销-> ajax登录-> ajax注销.

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

实际上,ajax登录/注销不提供任何输出.

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.

推荐答案

在将Principal手动添加到SecurityContext时,不会将用户添加到SessionRegistry.您需要手动将用户会话添加到SessionRegistry.

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

希望有帮助!

这篇关于手动进行身份验证时,使用sessionRegistry登录的用户无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆