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>
如果您使用 user
和 role
表以确保安全,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 可用,这与关系数据库的数据建模有很大不同。基本规则是:
- 了解分区键和簇键
- 为您的查询建模,而不是数据
- 索引效率不高
我正在尝试使用 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>
如果您使用 user
和 role
表以确保安全,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 可用,这与关系数据库的数据建模有很大不同。基本规则是:
- 了解分区键和簇键
- 为您的查询建模,而不是数据
- 索引效率不高