Spring Cassandra 安全认证失败

Spring Security With Cassandra-Authentication Failed

我正在尝试使用 Cassandra 数据库的 spring 安全性对用户进行身份验证。我遇到以下异常:

Authentication Failed: PreparedStatementCallback; bad SQL grammar [select userName, password from user where userName=?];
 nested exception is java.sql.SQLSyntaxErrorException: 
 No indexed columns present in by-columns clause with "equals" operator 'select userName, password from user where userName=?'

配置详情如下:

安全-config.xml

 <form-login 
     login-processing-url="/j_spring_security_check"
     login-page="/index.xhtml"  always-use-default-target="true"
                 authentication-failure-url="/index.xhtml?error=true"
                 authentication-success-handler-ref="authenticationSuccessHandler"
                 authentication-failure-handler-ref="authenticationFailureHandler"/>

<authentication-manager alias="authenticationManager">
        <authentication-provider>
            <jdbc-user-service data-source-ref="cassandraDataSource" users-by-username-query="select userName, password from user where userName=?"
                               authorities-by-username-query="select roleId, userName, roleName from role where userName=?"/>
        </authentication-provider>
    </authentication-manager>

并且我使用 cql 命令创建了索引:

CREATE INDEX userName_index ON role (userName);
CREATE INDEX userNameUser_index ON user (userName);

desc mykeyspaces 的结果

CREATE TABLE role (
    roleid int PRIMARY KEY,
    rolename text,
    username text
) WITH bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
CREATE INDEX userName_index ON role (username);

CREATE TABLE user (
    userid int PRIMARY KEY,
    email text,
    firstname text,
    lastname text,
    password text,
    phone int,
    username text
) WITH bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'min_threshold': '4', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
CREATE INDEX userNameUser_index ON user (username);

cqlsh:system>

如果您使用 userrole 表以确保安全,username 应该是这两个表的分区键。仅仅索引它们将导致查询多个节点并且不会有效。下面的数据模型将对您的查询更有效。

CREATE TABLE user (
    userid int,
    email text,
    firstname text,
    lastname text,
    password text,
    phone int,
    username text,
    PRIMARY KEY ((username), userid)

) 

CREATE TABLE role (
    roleid int,
    rolename text,
    username text,
    PRIMARY KEY ((username), roleid)
)

如您所见,主键由两列组成,以确保唯一性,但只有第一列是分区键。这确保该用户的所有记录都在一个节点上,并且按用户名查询将有效。

关于 Cassandra 的数据建模,有很多 info 可用,这与关系数据库的数据建模有很大不同。基本规则是:

  • 了解分区键和簇键
  • 为您的查询建模,而不是数据
  • 索引效率不高