2010-06-08 3 views
36

Est-il possible de modifier le rôle postgresql qu'un utilisateur utilise lorsqu'il interagit avec postgres après la connexion initiale? La ou les bases de données seront utilisées dans une application Web et j'utiliserai des règles de niveau de base de données sur les tables et les schémas avec le regroupement de connexions. A la lecture de la documentation postgresql, il semble que je puisse changer de rôle si je me connectais initialement en tant qu'utilisateur avec le rôle de superutilisateur, mais je préférerais initialement me connecter en tant qu'utilisateur avec un minimum d'autorisations et passer au besoin. Avoir à spécifier le mot de passe de l'utilisateur lors du changement serait bien (en fait je le préfère).Rôle de commutateur après la connexion à la base de données

Qu'est-ce qui me manque?

Mise à jour: J'ai essayé à la fois SET ROLE et SET SESSION AUTHORIZATION comme suggéré par @Milen cependant ni commande semble fonctionner si l'utilisateur n'est pas un super-utilisateur:

$ 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 

Répondre

7
+0

J'ai essayé deux commandes en vain, si l'utilisateur de connexion est pas un super-utilisateur j'obtenir la permission des erreurs a nié. J'ai mis à jour la question avec des informations supplémentaires –

+1

Je crois que votre utilisateur doit être membre des ROLES que vous voulez déjà définir et avoir la propriété NOINHERITS sur leur utilisateur afin qu'ils ne soient pas par défaut. Ensuite, vous devriez augmenter et désamorcer. Mais ils doivent déjà être membres du ROLE. – rfusca

30
--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 est maintenant dans le groupe neil, donc webgui peut appeler set role neil. Toutefois, webgui n'a pas hérité des autorisations neil.

plus tard, connectez-vous comme webgui:

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

set role neil; 

webgui n'a pas besoin superuser l'autorisation pour cela.

Vous souhaitez set role au début d'une session de base de données et le réinitialiser à la fin de la session. Dans une application Web, cela correspond à l'obtention d'une connexion à partir du pool de connexions de votre base de données et à sa libération, respectivement. Voici un exemple en utilisant le pool de connexion de Tomcat et 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); 
    } 
} 
Questions connexes