将CQ 5.6.1(jdk 1.7)迁移到AEM 6.4(jdk 1.8),使用Serializer <simplesession>从Cassandra读取会话时无法反序列化字节数组

时间:2018-07-26 04:00:14

标签: apache shiro

我正在将Java捆绑包从CQ 5.6.1迁移到AEM 6.4,该捆绑包在jdk 1.7中工作,

代码使用apache shiro来实现会话的序列化和反序列化,这是保存和读取存储在Cassandra中的会话的代码

当我将其迁移到AEM 6.4(在jdk 1.8中工作)时,它与AEM 5.6.1和6.1(在jdk 1.7中工作)工作良好,代码是 尝试在咬合数组中反序列化会话时在“ method doReadSession”中给出异常

它抛出异常 在方法doReadSession中,它返回“ serializer.deserialize(bytes)”

抛出的异常是

原因:org.apache.shiro.io.SerializationException:无法反序列化参数字节数组。     在org.apache.shiro.io.DefaultSerializer.deserialize(DefaultSerializer.java:82)     在com.xyz.web.platform.common.security.shiro.cassandra.CassandraSessionDAO.doReadSession(CassandraSessionDAO.java:252)     在org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:168)     在org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)

 import com.xyz.web.platform.common.security.shiro.session.idgenerator.UUIDSessionIdGenerator;
import com.xyz.web.platform.common.tracelogging.TMTraceLogger;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import org.apache.shiro.ShiroException;
import org.apache.shiro.io.DefaultSerializer;
import org.apache.shiro.io.Serializer;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.apache.shiro.util.Destroyable;
import org.apache.shiro.util.Initializable;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;


public class CassandraSessionDAO extends AbstractSessionDAO implements Initializable, Destroyable {

    private static final TMTraceLogger CASSANDRA_LOGGER = TMTraceLogger
            .getLogger("cassandraLogger" + "." + CassandraSessionDAO.class.getName());

    private String DEFAULT_CONSISTENCY_LEVEL = ConsistencyLevel.LOCAL_QUORUM.toString();
    private static final String DEFAULT_CACHING = "ROWS_ONLY";
    private static final String DEFAULT_DATA_CENTER = "DC1";



    private String keyspaceName;
    private String tableName;
    private Cluster cluster;
    private Serializer<SimpleSession> serializer;
    private String readConsistencyLevel;
    private String writeConsistencyLevel;
    private String defaultTTL;
    private String gc_grace_seconds;

    private String caching = DEFAULT_CACHING;
    private String dataCenter = DEFAULT_DATA_CENTER;

    private PreparedStatement deletePreparedStatement;
    private PreparedStatement savePreparedStatement;
    private PreparedStatement readPreparedStatement;

    private com.datastax.driver.core.Session cassandraSession;

    public CassandraSessionDAO() {

        setSessionIdGenerator(new UUIDSessionIdGenerator());
        this.serializer = new DefaultSerializer<SimpleSession>();
    }

    private SimpleSession assertSimpleSession(Session session) {
        if (!(session instanceof SimpleSession)) {
            throw new IllegalArgumentException(CassandraSessionDAO.class.getName() + " implementations only support "
                    + SimpleSession.class.getName() + " instances.");
        }
        return (SimpleSession) session;
    }

    public Cluster getCluster() {
        return cluster;
    }

    public void setCluster(Cluster cluster) {
        this.cluster = cluster;
    }

    public String getKeyspaceName() {
        return keyspaceName;
    }

    public void setKeyspaceName(String keyspaceName) {
        this.keyspaceName = keyspaceName;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getReadConsistencyLevel() {
        return readConsistencyLevel;
    }

    public void setReadConsistencyLevel(String readConsistencyLevel) {
        this.readConsistencyLevel = readConsistencyLevel;
    }

    public String getWriteConsistencyLevel() {
        return writeConsistencyLevel;
    }

    public void setWriteConsistencyLevel(String writeConsistencyLevel) {
        this.writeConsistencyLevel = writeConsistencyLevel;
    }

    public String getDefaultTTL() {
        return defaultTTL;
    }

    public void setDefaultTTL(String defaultTTL) {
        this.defaultTTL = defaultTTL;
    }

    public String getGc_grace_seconds() {
        return gc_grace_seconds;
    }

    public void setGc_grace_seconds(String gc_grace_seconds) {
        this.gc_grace_seconds = gc_grace_seconds;
    }

    public String getCaching() {
        return caching;
    }

    public void setCaching(String caching) {
        this.caching = caching;
    }

    public String getDataCenter() {
        return dataCenter;
    }

    public void setDataCenter(String dataCenter) {
        this.dataCenter = dataCenter;
    }

    public void init() throws ShiroException {
        com.datastax.driver.core.Session systemSession = cluster.connect();
        boolean create = false;
        try {
            if (!isKeyspacePresent(systemSession)) {
                create = true;
                createKeyspace(systemSession);
                if (!isKeyspacePresent(systemSession)) {
                    throw new IllegalStateException("Unable to create keyspace " + keyspaceName);
                }
            }
        } finally {
            systemSession.shutdown();
        }

        cassandraSession = cluster.connect(keyspaceName);
        if (create) {
            createTable();
        }

        prepareReadStatement();
        prepareSaveStatement();
        prepareDeleteStatement();
    }

    public void destroy() throws Exception {
        if (cassandraSession != null) {
            cassandraSession.shutdown();
            cluster.shutdown();
        }
    }

    protected boolean isKeyspacePresent(com.datastax.driver.core.Session systemSession) {
        PreparedStatement ps = systemSession.prepare("select * from system.schema_keyspaces");
        BoundStatement bs = new BoundStatement(ps);
        ResultSet results = systemSession.execute(bs);
        // ResultSet results = systemSession.execute("select * from
        // system.schema_keyspaces");
        for (Row row : results) {
            if (row.getString("keyspace_name").equalsIgnoreCase(keyspaceName)) {
                return true;
            }
        }
        return false;
    }

    protected void createKeyspace(com.datastax.driver.core.Session systemSession) {
        String query = "create keyspace " + this.keyspaceName
                + " with replication = {'class' : 'NetworkTopologyStrategy', '" + dataCenter + "': 2};";
        systemSession.execute(query);
    }

    protected void createTable() {

        long defaultTTLLong = Long.parseLong(defaultTTL);
        long gc_grace_secondsLong = Long.parseLong(gc_grace_seconds);
        String query = "CREATE TABLE " + tableName + " ( " + "    id varchar PRIMARY KEY, " + "    start_ts timestamp, "
                + "    stop_ts timestamp, " + "    last_access_ts timestamp, " + "    timeout bigint, "
                + "    expired boolean, " + "    host varchar, " + "    serialized_value blob " + ") " + "WITH "
                + "    gc_grace_seconds = " + gc_grace_secondsLong + " AND default_time_to_live = " + defaultTTLLong
                + " AND caching = '" + caching + "' AND " + "    compaction = {'class':'LeveledCompactionStrategy'};";
        cassandraSession.execute(query);
    }

    @Override
    protected Serializable doCreate(Session session) {
        SimpleSession ss = assertSimpleSession(session);
        Serializable timeUuid = generateSessionId(session);
        assignSessionId(ss, timeUuid);
        save(ss);
        return timeUuid;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {

        long startTime = System.currentTimeMillis();
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("In the doReadSession()..");
            CASSANDRA_LOGGER.logDebug("The start time is " + startTime + " ms");
        }

        // put a not-null & not-empty check
        if (sessionId != null && !sessionId.equals("")) {

            String id = sessionId.toString();

            PreparedStatement ps = prepareReadStatement();
            /*
             * String query = "SELECT * from " + tableName + " where id = ?";
             * PreparedStatement ps = cassandraSession.prepare(query);
             */
            BoundStatement bs = new BoundStatement(ps);
            bs.bind(id);
            if (readConsistencyLevel == null) {
                readConsistencyLevel = DEFAULT_CONSISTENCY_LEVEL;
            }
            bs.setConsistencyLevel(ConsistencyLevel.valueOf(readConsistencyLevel));
            ResultSet results = cassandraSession.execute(bs);
            for (Row row : results) {
                String rowId = row.getString("id");
                if (id.equals(rowId)) {
                    ByteBuffer buffer = row.getBytes("serialized_value");
                    if (buffer != null) {
                        byte[] bytes = new byte[buffer.remaining()];
                        buffer.get(bytes);
                        return serializer.deserialize(bytes);
                    }

                }
            }
        }
        long endTime = System.currentTimeMillis();
        long timeTaken = endTime - startTime;
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("The total time taken is " + timeTaken + " ms");
        }
        return null;
    }

    private PreparedStatement prepareReadStatement() {
        if (this.readPreparedStatement == null) {
            String query = "SELECT * from " + tableName + " where id = ?";
            this.readPreparedStatement = cassandraSession.prepare(query);
        }
        return this.readPreparedStatement;
    }

    // In CQL, insert and update are effectively the same, so we can use a single
    // query for both:
    protected void save(SimpleSession ss) {
        // long timeoutInSeconds = ss.getTimeout() / 1000;
        /*
         * String query = "UPDATE " + tableName + " SET " + "start_ts = ?, " +
         * "stop_ts = ?, " + "last_access_ts = ?, " + "timeout = ?, " + "expired = ?, "
         * + "host = ?, " + "serialized_value = ? " + "WHERE " + "id = ?";
         * PreparedStatement ps = cassandraSession.prepare(query);
         */
        long startTime = System.currentTimeMillis();
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("In the save()..");
            CASSANDRA_LOGGER.logDebug("The start time is " + startTime + " ms");
        }
        PreparedStatement ps = prepareSaveStatement();
        BoundStatement bs = new BoundStatement(ps);
        byte[] serialized = serializer.serialize(ss);
        ByteBuffer bytes = ByteBuffer.wrap(serialized);



        bs.bind(ss.getStartTimestamp(), ss.getStopTimestamp() != null ? ss.getStartTimestamp() : null,
                ss.getLastAccessTime(), ss.getTimeout(), ss.isExpired(), ss.getHost(), bytes, ss.getId().toString());
        if (writeConsistencyLevel == null) {
            writeConsistencyLevel = DEFAULT_CONSISTENCY_LEVEL;
        }
        bs.setConsistencyLevel(ConsistencyLevel.valueOf(writeConsistencyLevel));
        cassandraSession.execute(bs);
        long endTime = System.currentTimeMillis();
        long timeTaken = endTime - startTime;
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("The total time taken is " + timeTaken + " ms");
        }
    }

    private PreparedStatement prepareSaveStatement() {
        if (this.savePreparedStatement == null) {
            String query = "UPDATE " + tableName + " SET " + "start_ts = ?, " + "stop_ts = ?, " + "last_access_ts = ?, "
                    + "timeout = ?, " + "expired = ?, " + "host = ?, " + "serialized_value = ? " + "WHERE " + "id = ?";
            this.savePreparedStatement = cassandraSession.prepare(query);
        }
        return this.savePreparedStatement;
    }

    public void update(Session session) throws UnknownSessionException {
        SimpleSession ss = assertSimpleSession(session);
        save(ss);
    }

    public void delete(Session session) {
        /*
         * String query = "DELETE from " + tableName + " where id = ?";
         * PreparedStatement ps = cassandraSession.prepare(query);
         */

        long startTime = System.currentTimeMillis();
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("In the delete()..");
            CASSANDRA_LOGGER.logDebug("The start time is " + startTime + " ms");
        }
        PreparedStatement ps = prepareDeleteStatement();
        BoundStatement bs = new BoundStatement(ps);
        bs.bind(session.getId().toString());
        cassandraSession.execute(bs);
        long endTime = System.currentTimeMillis();
        long timeTaken = endTime - startTime;
        if (CASSANDRA_LOGGER.isDebugEnabled()) {
            CASSANDRA_LOGGER.logDebug("The total time taken is " + timeTaken + " ms");
        }
    }

    private PreparedStatement prepareDeleteStatement() {
        if (this.deletePreparedStatement == null) {
            String query = "DELETE from " + tableName + " where id = ?";
            this.deletePreparedStatement = cassandraSession.prepare(query);
        }
        return this.deletePreparedStatement;
    }

    public Collection<Session> getActiveSessions() {
        return Collections.emptyList();
    }

}

1 个答案:

答案 0 :(得分:0)