4

spring security3 と spring mvc3 を使用して Web プロジェクトを構築しています。index.jspというページがあり、この画面の上部にログインユーザー名とオンラインユーザー数が表示されます。システムにログインするには、次の 2 つの方法があります。

  1. ログインページから、「j_spring_security_check」によるデフォルト設定投稿を使用
  2. 手動認証による ajax ログイン

ログイン ページを使用してインデックス ページにログインすると、オンライン情報のカウントとユーザー名の両方が正しく表示されます。しかし、ajax ログイン (手動認証) を使用すると、問題が発生します。オンライン ユーザーの数が更新されず、ユーザー名が正しく表示されている間、常に 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\"}";
            }
}

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>

オンラインログインユーザー数を取得するために使用した方法:

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

}

以下は、アクション シーケンスのログ ファイルの主な内容です: 通常のログイン -> 通常のログアウト -> ajax ログイン -> ajax ログアウト。

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

実際、ajaxログイン/ログアウトでは何も出力されません。

では、正しいログイン ユーザー数を取得するにはどうすればよいでしょうか。また、認証方法が異なると、セッションを処理する方法が異なるのはなぜですか? どんな助けでも大歓迎です。

4

2 に答える 2

3

に手動で追加PrincipalしているためSecurityContext、ユーザーは に追加されませんSessionRegistrySessionRegistryユーザーセッションを手動で追加する必要があります。

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

それが役に立てば幸い!!

于 2014-12-12T12:45:55.093 に答える
0

Springspring-security.xmlファイルで、AJAX 認証 ( ) の URL が/ajaxLogin明示的に許可されていません。したがって、リクエストは Spring によってブロックされます。これを追加することをお勧めします:

<intercept-url pattern="/ajaxLogin" access="permitAll" />
于 2013-08-18T06:17:41.967 に答える