Cas implementation of subsystem login and mutual kick

Keywords: Session Java Google JSON

Implementation ideas

1. A class, which maintains a map of the logged in user, takes out the corresponding session of the last user every time when logging in, and adds an expired attribute ID lasthttpsession.setattribute (be ﹣ "your account is logged in at another location, and you are forced to log off")

2. Write a sessionFilter. The sessionFilter takes out the sessions maintained in each request instance, and judges whether there is be "kicked" in the session

3. If there is one, it means that the session is the kicked user and returns the kicked information to the client

No more bullshit, just code it

UserStatistiUtil 

package com.gysoft.sso.utils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import javax.servlet.http.HttpSession;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author Zhou Ning
 * @Date 2018-06-13 20:14
 */
public class UserStatisticUtil {
    /**
     * Default cache 2 hours
     */
    public static final Integer DEFAULT_CACHE_SECONDS = 60*60*2;
    /**
     * Default size of cache container
     */
    private static final Integer DEFAULT_SIZE = 10000;

    /**
     * Store the map of the Session corresponding to the user, which is used to kick out the user
     */
    public static ConcurrentHashMap<String,HttpSession> userSessionMap = new ConcurrentHashMap();

    /**
     * Cache container to store the session ID of the kicked user. If a kicked user requests after 2 hours, it is the session timeout instead of being kicked
     */
    private static final Cache<String, HttpSession> invalidSessionIdMap = CacheBuilder.newBuilder().maximumSize(DEFAULT_SIZE)
            .expireAfterWrite(DEFAULT_CACHE_SECONDS, TimeUnit.SECONDS).build();
    /**
     * Determine whether it is an expired sessionId
     * @param sessionId
     * @return
     */
    public static boolean isInvalidSessionId(String sessionId){
        return getInvalidSessionId(sessionId)!=null;
    }
    /**
     * Retrieve the expired sessionId
     * @param key
     * @return Object
     */
    public static HttpSession getInvalidSessionId(String key) {
        return invalidSessionIdMap.getIfPresent(key);
    }

    /**
     * Put the expired sessionId
     * @param key
     * @param value
     */
    public static void putInvalidSessionId(String key, HttpSession value) {
        invalidSessionIdMap.put(key, value);
    }

}

CustomCas30ProxyReceivingTicketValidationFilter

public class CustomCas30ProxyReceivingTicketValidationFilter extends Cas30ProxyReceivingTicketValidationFilter {
    @Override
    protected void onSuccessfulValidation(HttpServletRequest request, HttpServletResponse response, Assertion assertion) {
        String username =assertion.getPrincipal().getName();
        HttpSession lastHttpSession = UserStatisticUtil.userSessionMap.get(username);
        if(null!=lastHttpSession&&!UserStatisticUtil.isInvalidSessionId(lastHttpSession.getId())){
            try{
                lastHttpSession.setAttribute(BE_KICKED,"Your account is logged in at another location,You are forced to go offline");
            }catch (IllegalStateException e){
                //The reason for TODO Nothing is that the session of the browser is expired but not cleared in time
            }
        }
        String dcpLoginInfo = (String) assertion.getPrincipal().getAttributes().get(DCP_LOGIN_INFO);
        HttpSession session = request.getSession();
        session.setAttribute(DCP_LOGIN_INFO,dcpLoginInfo);
        UserStatisticUtil.userSessionMap.put(username,session);
    }
}

 

SessionTimeOutFilter

package com.gysoft.sso.filter;


import com.gysoft.sso.utils.UserStatisticUtil;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

import static com.gysoft.sso.bean.SessionVariable.BE_KICKED;
import static com.gysoft.sso.bean.SessionVariable.DCP_LOGIN_INFO;
import static com.gysoft.sso.utils.UserStatisticUtil.DEFAULT_CACHE_SECONDS;

/**
 * session Timeout filtering
 * @author Zhou Ning
 * @Date 2018-06-12 14:08
 */
public class SessionTimeOutFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        HttpSession session = req.getSession();
        String queryString = req.getQueryString();
        //If the url address needs single point authentication and the session does not exist, you need to verify whether the address contains ticket
        if(!CustomAuthenticationFilter.isRequestUrlExcluded(req)&&session.getAttribute(DCP_LOGIN_INFO)==null){
            if(queryString==null||queryString.indexOf("ticket")==-1){
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().write("{\"msg\": \"User not logged in\",\"code\": " + 302 + ",\"result\":  "+null+"}");
                return;
            }
        }
        //Online kicking
        if(session.getAttribute(BE_KICKED)!=null){
            UserStatisticUtil.putInvalidSessionId(session.getId(),session,DEFAULT_CACHE_SECONDS);
            String msg = (String) session.getAttribute(BE_KICKED);
            session.invalidate();
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write("{\"msg\": "+msg+",\"code\": " + 302 + ",\"result\": " + null + "}");
            return;
        }
        chain.doFilter(req,res);
    }

    @Override
    public void destroy() {

    }
}

 

Posted by drorgo on Sat, 16 Nov 2019 09:21:31 -0800