Switch role after connecting to database
在初始连接后与postgres交互时,是否可以更改用户正在使用的postgresql角色?
数据库将在Web应用程序中使用,我希望对具有连接池的表和模式使用数据库级规则。 从阅读postgresql文档看来,如果我最初作为具有超级用户角色的用户连接,我可以切换角色,但我更愿意最初以具有最小权限的用户连接并根据需要进行切换。 切换时必须指定用户的密码才行(实际上我更喜欢它)。
我错过了什么?
更新:我已经按照@Milen的建议尝试了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $ 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 |
1 2 3 4 5 6 7 8 9 10 11 | --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身份登录:
1 2 3 4 | psql -d some_database -U webgui (enter s3cr3t AS password) SET ROLE neil; |
您希望在数据库会话开始时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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); } } |
看看"SET ROLE"和"SET SESSION AUTHORIZATION"。
如果有人仍然需要它(就像我一样)。
The specified role_name must be a role that the current session user is a member of.
https://www.postgresql.org/docs/10/sql-set-role.html
我们需要使当前会话用户成为角色的成员:
1 2 3 4 | CREATE ROLE myrole; SET ROLE myrole; GRANT myrole TO myuser; SET ROLE myrole; |
生产:
1 2 3 4 5 6 7 8 9 10 11 12 | ROLE ROLE created. Error starting at line : 4 IN command - SET ROLE myrole Error report - ERROR: permission denied TO SET ROLE"myrole" GRANT succeeded. ROLE SET succeeded. |