连接数据库后切换角色

Chr*_*Gow 58 postgresql

在初始连接后与postgres交互时,是否可以更改用户正在使用的postgresql角色?

数据库将在Web应用程序中使用,我希望对具有连接池的表和模式使用数据库级规则.从阅读postgresql文档看来,如果我最初作为具有超级用户角色的用户连接,我可以切换角色,但我更愿意最初以具有最小权限的用户连接并根据需要进行切换.切换时必须指定用户的密码才行(实际上我更喜欢它).

我错过了什么?

更新:我已经尝试了两个SET ROLE并且SET SESSION AUTHORIZATION按照@Milen的建议但是如果用户不是超级用户,那么两个命令似乎都不起作用:

$ psql -U test
psql (8.4.4)
Type "help" for help.

test=> \du test
          List of roles
 Role name | Attributes |   Member of    
-----------+------------+----------------
 test      |            | {connect_only}

test=> \du test2
          List of roles
 Role name | Attributes |   Member of    
-----------+------------+----------------
 test2     |            | {connect_only}

test=> set role test2;
ERROR:  permission denied to set role "test2"
test=> \q
Run Code Online (Sandbox Code Playgroud)

Nei*_*gan 44

--create a user that you want to use the database as:

create role neil;

--create the user for the web server to connect as:

create role webgui noinherit login password 's3cr3t';

--let webgui set role to neil:

grant neil to webgui; --this looks backwards but is correct.
Run Code Online (Sandbox Code Playgroud)

webgui现在是neil小组,所以webgui可以打电话set role neil.但是,webgui没有继承neil权限.

稍后,以webgui身份登录:

psql -d some_database -U webgui
(enter s3cr3t as password)

set role neil;
Run Code Online (Sandbox Code Playgroud)

webgui不需要superuser这个许可.

您希望set role在数据库会话开始时在会话结束时重置它.在Web应用程序中,这分别对应于从数据库连接池获取连接并释放它.这是使用Tomcat的连接池和Spring Security的示例:

public class SetRoleJdbcInterceptor extends JdbcInterceptor {

    @Override
    public void reset(ConnectionPool connectionPool, PooledConnection pooledConnection) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if(authentication != null) {
            try {

                /* 
                  use OWASP's ESAPI to encode the username to avoid SQL Injection. Can't use parameters with SET ROLE. Need to write PG codec.

                  Or use a whitelist-map approach
                */
                String username = ESAPI.encoder().encodeForSQL(MY_CODEC, authentication.getName());

                Statement statement = pooledConnection.getConnection().createStatement();
                statement.execute("set role \"" + username + "\"");
                statement.close();
            } catch(SQLException exp){
                throw new RuntimeException(exp);
            }
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        if("close".equals(method.getName())){
            Statement statement = ((Connection)proxy).createStatement();
            statement.execute("reset role");
            statement.close();
        }

        return super.invoke(proxy, method, args);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mil*_*dev 12

看看"SET ROLE""SET SESSION AUTHORIZATION".

  • 我相信您的用户必须是您已经要设置的ROLES的成员,并且在其用户上具有NOINHERITS属性,这样它们才不会成为默认设置。然后,您应该升级并降级。但是他们必须已经是ROLE的成员。 (2认同)