2 回答
TA贡献1815条经验 获得超12个赞
这是在mybatis-spring的帮助下完成您需要的操作的简单方法。
除非您已经使用 mybatis-spring,否则第一步是更改项目的配置,以便您使用SqlSessionFactory
mybatis org.mybatis.spring.SqlSessionFactoryBean
-spring 提供的功能。
下一步是设置/重置连接的用户角色。在mybatis中,连接生命周期由实现接口的类控制org.apache.ibatis.transaction.Transaction
。查询执行器使用此类的实例来获取连接。
简而言之,您需要创建自己的此类实现并配置 mybatis 来使用它。
您的实现可以基于SpringManagedTransaction
mybatis-spring ,并且看起来像:
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
// https://stackoverflow.com/questions/2998597/switch-role-after-connecting-to-database
// 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
实现。为此,您需要实现TransactionFactory
类似于mybatis-springorg.mybatis.spring.transaction.SpringManagedTransactionFactory
提供的功能:
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) {
}
}
然后UserRoleAwareSpringManagedTransactionFactory在 spring 上下文中定义一个类型的 bean 并将其注入到spring 上下文中transactionFactory的属性中。SqlSessionFactoryBeen
现在mybatis每次获取到Connection执行Transaction都会设置当前的spring security用户来设置角色。
TA贡献1851条经验 获得超3个赞
最佳实践是数据库用户是应用程序。应用程序用户对特定数据/资源的访问应在应用程序中进行控制。应用程序不应依赖数据库来限制数据/资源访问。因此,应用程序用户不应该在数据库中具有不同的角色。应用程序应仅使用单个数据库用户帐户。
Spring是最佳实践的体现。因此Spring并没有实现这个功能。如果你想要这样的功能,你需要破解。您最好的选择是:
@Autowired JdbcTemplate jdbcTemplate;
// ...
public runPerUserSql() {
jdbcTemplate.execute("set role user 'user_1';");
jdbcTemplate.execute("SELECT 1;");
}
对此我还是没有太大的信心。除非您正在为多个用户编写 pgAdmin Web 应用程序,否则您应该重新考虑您的方法和设计。
添加回答
举报