postgresql(set role user)命令在SSM项目中如何使用?
How does the postgresql (set role user) command use in SSM projects?
现在项目使用的是springmvc+ spring + mybatis + druid + postgresql
项目中的用户对应数据库中的用户,所以每次运行SQL都是通过(set role user)命令切换用户,然后进行数据库的crud操作。
我的问题:
因为连接池中有很多连接,所以第一步是获取数据库的连接,然后切换用户,再对数据库进行业务SQL的操作。但是不知道这个逻辑应该在项目的哪一部分处理,因为连接池的连接和SQL的执行都是底层代码实现的。你有什么好的计划吗?
能不能给我一个完整的demo,比如下面的操作:
第 1 步,从 spring security(或 shiro)获取用户名。
第二步,从连接池中获取当前使用数据库的连接
第三步,执行SQL(设置角色用户)进行角色切换
第四步,执行crud操作
第五步,重置数据库连接(重置角色)
最佳做法是数据库用户是应用程序。应在应用程序中控制应用程序用户对特定 data/resource 的访问。应用程序不应依赖数据库来限制 data/resource 访问。因此,应用程序用户不应在数据库中具有不同的角色。一个应用程序应该只使用一个数据库用户帐户。
Spring 是最佳实践的体现。因此,Spring 没有实现这个功能。如果你想要这样的功能,你需要破解。
关于 this,您最好的选择是:
@Autowired JdbcTemplate jdbcTemplate;
// ...
public runPerUserSql() {
jdbcTemplate.execute("set role user 'user_1';");
jdbcTemplate.execute("SELECT 1;");
}
我对此还是没有太大信心。除非您正在为多个用户编写 pgAdmin webapp,否则您应该重新考虑您的方法和设计。
这是在 mybatis-spring 的帮助下完成所需操作的简单方法。
除非你已经在使用 mybatis-spring 否则第一步是更改你的项目的配置,这样你就可以使用 mybatis-[=46 提供的 org.mybatis.spring.SqlSessionFactoryBean
获得 SqlSessionFactory
=].
下一步是 setting/resetting 连接的用户角色的实施。在 mybatis 中,连接生命周期由 class 实现 org.apache.ibatis.transaction.Transaction
接口控制。这个class的实例被查询执行器用来获取连接。
简而言之,您需要创建自己的实现 class 并配置 mybatis 以使用它。
您的实现可以基于 mybatis-spring 中的 SpringManagedTransaction
并且看起来像:
import org.springframework.security.core.Authentication;
class UserRoleAwareSpringManagedTransaction extends SpringManagedTransaction {
public UserRoleAwareSpringManagedTransaction(DataSource dataSource) {
super(dataSource);
}
@Override
public Connection getConnection() throws SQLException {
Connection connection = getCurrentConnection();
setUserRole(connection);
return connection;
}
private Connection getCurrentConnection() {
return super.getConnection();
}
@Override
public void close() throws SQLException {
resetUserRole(getCurrentConnection());
super.close();
}
private void setUserRole(Connection connection) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
Statement statement = connection.createStatement();
try {
// note that this direct usage of usernmae is a subject for SQL injection
// so you need to use the suggestion from
//
// about encoding of the username
statement.execute("set role '" + username + "'");
} finally {
statement.close();
}
}
private void resetUserRole(Connection connection) {
Statement statement = connection.createStatement();
try {
statement.execute("reset role");
} finally {
statement.close();
}
}
}
现在您需要配置 mybatis 以使用您的 Transaction
实现。为此,您需要实施类似于 mybatis-spring:
提供的 org.mybatis.spring.transaction.SpringManagedTransactionFactory
的 TransactionFactory
public class UserRoleAwareSpringManagedTransactionFactory implements TransactionFactory {
@Override
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
return new UserRoleAwareSpringManagedTransaction(dataSource);
}
@Override
public Transaction newTransaction(Connection conn) {
throw new UnsupportedOperationException("New Spring transactions require a DataSource");
}
@Override
public void setProperties(Properties props) {
}
}
然后在你的 spring 上下文中定义一个类型为 UserRoleAwareSpringManagedTransactionFactory
的 bean,并将其注入到你的 SqlSessionFactoryBeen
的 transactionFactory
属性 中46=]上下文。
现在mybatis每次获取一个Connection
执行Transaction
都会设置当前spring安全用户来设置角色
现在项目使用的是springmvc+ spring + mybatis + druid + postgresql 项目中的用户对应数据库中的用户,所以每次运行SQL都是通过(set role user)命令切换用户,然后进行数据库的crud操作。
我的问题: 因为连接池中有很多连接,所以第一步是获取数据库的连接,然后切换用户,再对数据库进行业务SQL的操作。但是不知道这个逻辑应该在项目的哪一部分处理,因为连接池的连接和SQL的执行都是底层代码实现的。你有什么好的计划吗? 能不能给我一个完整的demo,比如下面的操作:
第 1 步,从 spring security(或 shiro)获取用户名。
第二步,从连接池中获取当前使用数据库的连接
第三步,执行SQL(设置角色用户)进行角色切换
第四步,执行crud操作
第五步,重置数据库连接(重置角色)
最佳做法是数据库用户是应用程序。应在应用程序中控制应用程序用户对特定 data/resource 的访问。应用程序不应依赖数据库来限制 data/resource 访问。因此,应用程序用户不应在数据库中具有不同的角色。一个应用程序应该只使用一个数据库用户帐户。
Spring 是最佳实践的体现。因此,Spring 没有实现这个功能。如果你想要这样的功能,你需要破解。
关于 this,您最好的选择是:
@Autowired JdbcTemplate jdbcTemplate;
// ...
public runPerUserSql() {
jdbcTemplate.execute("set role user 'user_1';");
jdbcTemplate.execute("SELECT 1;");
}
我对此还是没有太大信心。除非您正在为多个用户编写 pgAdmin webapp,否则您应该重新考虑您的方法和设计。
这是在 mybatis-spring 的帮助下完成所需操作的简单方法。
除非你已经在使用 mybatis-spring 否则第一步是更改你的项目的配置,这样你就可以使用 mybatis-[=46 提供的 org.mybatis.spring.SqlSessionFactoryBean
获得 SqlSessionFactory
=].
下一步是 setting/resetting 连接的用户角色的实施。在 mybatis 中,连接生命周期由 class 实现 org.apache.ibatis.transaction.Transaction
接口控制。这个class的实例被查询执行器用来获取连接。
简而言之,您需要创建自己的实现 class 并配置 mybatis 以使用它。
您的实现可以基于 mybatis-spring 中的 SpringManagedTransaction
并且看起来像:
import org.springframework.security.core.Authentication;
class UserRoleAwareSpringManagedTransaction extends SpringManagedTransaction {
public UserRoleAwareSpringManagedTransaction(DataSource dataSource) {
super(dataSource);
}
@Override
public Connection getConnection() throws SQLException {
Connection connection = getCurrentConnection();
setUserRole(connection);
return connection;
}
private Connection getCurrentConnection() {
return super.getConnection();
}
@Override
public void close() throws SQLException {
resetUserRole(getCurrentConnection());
super.close();
}
private void setUserRole(Connection connection) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
Statement statement = connection.createStatement();
try {
// note that this direct usage of usernmae is a subject for SQL injection
// so you need to use the suggestion from
//
// about encoding of the username
statement.execute("set role '" + username + "'");
} finally {
statement.close();
}
}
private void resetUserRole(Connection connection) {
Statement statement = connection.createStatement();
try {
statement.execute("reset role");
} finally {
statement.close();
}
}
}
现在您需要配置 mybatis 以使用您的 Transaction
实现。为此,您需要实施类似于 mybatis-spring:
org.mybatis.spring.transaction.SpringManagedTransactionFactory
的 TransactionFactory
public class UserRoleAwareSpringManagedTransactionFactory implements TransactionFactory {
@Override
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
return new UserRoleAwareSpringManagedTransaction(dataSource);
}
@Override
public Transaction newTransaction(Connection conn) {
throw new UnsupportedOperationException("New Spring transactions require a DataSource");
}
@Override
public void setProperties(Properties props) {
}
}
然后在你的 spring 上下文中定义一个类型为 UserRoleAwareSpringManagedTransactionFactory
的 bean,并将其注入到你的 SqlSessionFactoryBeen
的 transactionFactory
属性 中46=]上下文。
现在mybatis每次获取一个Connection
执行Transaction
都会设置当前spring安全用户来设置角色