【问题标题】:How does the postgresql (set role user) command use in SSM projects?postgresql(设置角色用户)命令如何在 SSM 项目中使用?
【发布时间】:2019-09-05 02:03:45
【问题描述】:

现在项目使用的是springmvc+spring+mybatis+druid+postgresql 项目中的用户对应数据库中的用户,所以每次运行SQL都要通过(set role user)命令切换用户,然后进行数据库的crud操作。

我的问题: 因为连接池中有很多连接,所以第一步是获取数据库的连接,然后切换用户,然后对数据库进行业务SQL的操作。但是我不知道这个逻辑应该处理到项目的哪个部分,因为连接池的连接和SQL的执行都是由底层代码实现的。你有什么好的计划吗? 能否给我一个完整的demo,比如如下操作:

第 1 步,从 spring security(或 shiro)获取用户名。

第二步,从连接池中获取当前使用数据库的连接。

第三步,执行SQL(设置角色用户)切换角色。

第四步,进行crud操作。

第五步,重置数据库连接(重置角色)

【问题讨论】:

  • Can you provide me with a complete demo. Shirley 你不会是认真的吧?但是,您可能想查看相关的schema based multitenancy。因为每次调用都会改变的是架构,而不是角色。
  • 非常感谢您的建议,因为postgresql已经做了一些改动;数据库根据角色的权限加密,权限设计在数据库中(比如一张表有3个字段,Mike用户登录时只能看到2个字段,而Tom用户登录时只能看到1个字段) . web项目只需要告诉数据库登录的角色。获取对应的数据。

标签: java spring postgresql mybatis connection-pool


【解决方案1】:

这是一种在mybatis-spring 的帮助下完成您需要的简单方法。

除非您已经使用 mybatis-spring,否则第一步是更改项目的配置,以便使用 mybatis-spring 提供的org.mybatis.spring.SqlSessionFactoryBean 获得SqlSessionFactory

下一步是执行设置/重置连接的用户角色。在 mybatis 中,连接生命周期由实现org.apache.ibatis.transaction.Transaction 接口的类控制。查询执行器使用此类的实例来获取连接。

简而言之,您需要创建自己的此类实现并配置 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
      // 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实现。为此,您需要实现类似于mybatis-spring 提供的org.mybatis.spring.transaction.SpringManagedTransactionFactoryTransactionFactory

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,并将它注入到你的 spring 上下文中 SqlSessionFactoryBeentransactionFactory 属性中。

现在mybatis每次获取一个Connection的实现Transaction都会设置当前的spring security用户来设置角色。

【讨论】:

  • 非常感谢。你的回答对我帮助很大。
【解决方案2】:

最佳实践是数据库用户是应用程序。应在应用程序中控制应用程序用户对特定数据/资源的访问。应用程序不应依赖数据库来限制数据/资源访问。因此,应用程序用户不应在数据库中具有不同的角色。应用程序应该只使用一个数据库用户帐户。

Spring 是最佳实践的体现。因此,Spring 没有实现这个功能。如果你想要这样的功能,你需要破解。

参考this,您最好的选择是:

@Autowired JdbcTemplate jdbcTemplate; 

// ...

public runPerUserSql() {

    jdbcTemplate.execute("set role user 'user_1';");
    jdbcTemplate.execute("SELECT 1;");

}

我对此还是没有太大的信心。除非您正在为多个用户编写 pgAdmin webapp,否则您应该重新考虑您的方法和设计。

【讨论】:

  • 恐怕我无法提供完整的演示,因为这需要大量的黑客攻击。我强烈建议你修改你的设计,因为它不是很常见。
  • 非常感谢您的回复。在数据库中进行了一些更改。这种设计不是问题。现在最重要的是,在和项目结合的时候,出现了一些问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 2013-07-20
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多