Допустим у нас есть следующие декларации в конфиге Cassandra:
<Keyspace Name="Keyspace1"> <ColumnFamily Name="Configuration" CompareWith="UTF8Type"/> <ColumnFamily Name="Users" CompareWith="UTF8Type"/> ... </Keyspace>Мы объявили две ColumnFamily. В Users будем хранить записи пользователей, в Configuration общие настройки приложения, в частности в одной предопределенной записи, скажем с именем "GroupsAuthority", в столбцах будет определение групп и прав.
ColumnFamily:Users |-------------------------------------------------------------------------- |UserName\Property| enabled | group | password (MD5) | |-------------------------------------------------------------------------- |user1 | true | user,admin |24c9e15e52afc47c225b757e7bee1f9d| |userN | false | editor |362edb266f062db3ddbd1098b8affcbd| |-------------------------------------------------------------------------- ColumnFamily:Configuration |------------------------------------------------------------------- | | user | editor | admin | |------------------------------------------------------------------- |GroupsAuthority| canView | canEdit | canView, canEdit, canBackup| |-------------------------------------------------------------------
Далее необходимая конфигурация в Spring
<authentication-manager>
<authentication-provider user-service-ref="userServiceBean">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="userServiceBean" class="com.applusion.cassadraspring.CassandraHectorUserDetailsServiceImpl">
<beans:property name="cassandraClientPool" ref="cassandraClientPool"/>
<beans:property name="keyspace" value="Keyspace1"/>
<beans:property name="usersCF" value="Users"/>
<beans:property name="passwordColumn" value="password"/>
<beans:property name="enabledColumn" value="enabled"/>
<beans:property name="groupColumn" value="group"/>
<beans:property name="configurationCF" value="Configuration"/>
<beans:property name="groupsAuthorityKey" value="GroupsAuthority"/>
</beans:bean>
Не забудем совершенно типичную конфигурацию в Spring с использованием Cassandra и Hector:
<bean id="cassandraClientMonitor" class="me.prettyprint.cassandra.service.CassandraClientMonitor"/>
<bean id="jmxMonitor" class="me.prettyprint.cassandra.service.JmxMonitor" factory-method="getInstance"/>
<bean id="cassandraClientPoolFactory" class="me.prettyprint.cassandra.service.CassandraClientPoolFactory" factory-method="getInstance"/>
<bean id="cassandraClientPool" factory-bean="cassandraClientPoolFactory" factory-method="createNew" >
<constructor-arg><ref bean="cassandraHostConfigurator"/></constructor-arg>
</bean>
<bean id="cassandraHostConfigurator" class="me.prettyprint.cassandra.service.CassandraHostConfigurator">
<constructor-arg value="localhost:9160"/>
</bean>
Сам класс:
/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.applusion.cassadraspring;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.prettyprint.cassandra.dao.SpringCommand;
import me.prettyprint.cassandra.service.CassandraClient;
import me.prettyprint.cassandra.service.CassandraClientPool;
import me.prettyprint.cassandra.service.Keyspace;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.NotFoundException;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
* UserDetailsService implementation that reads user details from a Apache Cassandra.
*
* @author Oleg Smith
*/
public class CassandraHectorUserDetailsServiceImpl implements UserDetailsService {
private CassandraClientPool cassandraClientPool;
private String keyspace = "Keyspace1";
private String usersCF = "Standard2";
private String passwordColumn = "password";
private String enabledColumn = "enabled";
private String groupColumn = "group";
private String configurationCF="Configuration";
private String groupsAuthorityKey="GroupsAuthority";
private ConsistencyLevel consistencyLevel = CassandraClient.DEFAULT_CONSISTENCY_LEVEL;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
public CassandraHectorUserDetailsServiceImpl() {
}
public CassandraHectorUserDetailsServiceImpl(CassandraClientPool cassandraClientPool) {
this.cassandraClientPool = cassandraClientPool;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
List<Column> cl, cl2;
try {
cl = getUserProperties(username);
if (cl.size()==0) {
throw new UsernameNotFoundException(
messages.getMessage("CassandraHectorUserDetailsServiceImpl.notFound", new Object[]{username}, "Username {0} not found"), username);
}
cl2 = getGroupsAuthority();
if (cl2.size()==0) {
throw new UsernameNotFoundException(
messages.getMessage("CassandraHectorUserDetailsServiceImpl.notFound", new Object[]{username}, "Not found any GroupsAuthority in base"));
}
Map<String,String> userProperties=new HashMap<String,String>();
for (Column cli:cl) {
userProperties.put(new String(cli.name),new String(cli.value));
}
String[] userGroups=userProperties.get(groupColumn).split(",");
String password=userProperties.get(passwordColumn);
boolean enabled=userProperties.get(enabledColumn).trim().equals("true") ? true: false;
Map<String,String> groupsAuthority=new HashMap<String,String>();
for (Column cli:cl2) {
groupsAuthority.put(new String(cli.name),new String(cli.value));
}
List<String> authorities=new ArrayList<String>();
for (String userGroup:userGroups) {
String[] gauthorities=groupsAuthority.get(userGroup).split(",");
for (String authority:gauthorities) {
authorities.add(authority);
}
}
Collection<GrantedAuthority> dbAuths = new ArrayList<GrantedAuthority>();
for (String auth:authorities) {
if (!auth.equals("")) dbAuths.add(new GrantedAuthorityImpl(auth.trim()));
}
return new User(username, password, enabled, true,true, true, dbAuths);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public List<Column> getUserProperties(final String key) throws Exception {
return execute(new SpringCommand<List<Column>>(cassandraClientPool){
public List<Column> execute(final Keyspace ks) throws Exception {
try {
ColumnParent clp = new ColumnParent(usersCF);
SliceRange sr = new SliceRange(new byte[0], new byte[0], false, 150);
SlicePredicate sp = new SlicePredicate();
sp.setSlice_range(sr);
List<Column> cols = ks.getSlice(key, clp, sp);
return cols;
} catch (NotFoundException e) {
return null;
}
}
});
}
public List<Column> getGroupsAuthority() throws Exception {
return execute(new SpringCommand<List<Column>>(cassandraClientPool){
public List<Column> execute(final Keyspace ks) throws Exception {
try {
ColumnParent clp = new ColumnParent(configurationCF);
SliceRange sr = new SliceRange(new byte[0], new byte[0], false, 150);
SlicePredicate sp = new SlicePredicate();
sp.setSlice_range(sr);
List<Column> cols = ks.getSlice(groupsAuthorityKey, clp, sp);
return cols;
} catch (NotFoundException e) {
return null;
}
}
});
}
protected <T> T execute(SpringCommand<T> command) throws Exception {
CassandraClient c = cassandraClientPool.borrowClient();
Keyspace ks = c.getKeyspace(keyspace, consistencyLevel);
try {
return command.execute(ks);
} finally {
cassandraClientPool.releaseClient(ks.getClient());
}
}
public CassandraClientPool getCassandraClientPool() {
return cassandraClientPool;
}
public void setCassandraClientPool(CassandraClientPool cassandraClientPool) {
this.cassandraClientPool = cassandraClientPool;
}
public String getKeyspace() {
return keyspace;
}
public void setKeyspace(String keyspace) {
this.keyspace = keyspace;
}
public String getUsersCF() {
return usersCF;
}
public void setUsersCF(String usersCF) {
this.usersCF = usersCF;
}
public String getPasswordColumn() {
return passwordColumn;
}
public void setPasswordColumn(String passwordColumn) {
this.passwordColumn = passwordColumn;
}
public String getEnabledColumn() {
return enabledColumn;
}
public void setEnabledColumn(String enabledColumn) {
this.enabledColumn = enabledColumn;
}
public String getGroupColumn() {
return groupColumn;
}
public void setGroupColumn(String groupColumn) {
this.groupColumn = groupColumn;
}
public String getConfigurationCF() {
return configurationCF;
}
public void setConfigurationCF(String configurationCF) {
this.configurationCF = configurationCF;
}
public String getGroupsAuthorityKey() {
return groupsAuthorityKey;
}
public void setGroupsAuthorityKey(String groupsAuthorityKey) {
this.groupsAuthorityKey = groupsAuthorityKey;
}
public ConsistencyLevel getConsistencyLevel() {
return consistencyLevel;
}
public void setConsistencyLevel(ConsistencyLevel consistencyLevel) {
this.consistencyLevel = consistencyLevel;
}
}
Вроде все. Теперь в контроллере можно аннотациями ограничивать права. Например так PreAuthorize("hasRole('canBackup')")
Комментариев нет:
Отправить комментарий