是否可以更改用户在初始连接后与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
--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.
webgui现在在neil组中,所以webgui可以调用set role neil。但是,webgui没有继承neil的权限。
后来,登录为webgui:
psql -d some_database -U webgui (enter s3cr3t as password) set role neil;
webgui不需要超级用户权限。
您希望在数据库会话开始时设置角色,并在会话结束时将其重置。在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); } }